如何从 NSDocument 中分离 NSTextView 的撤消管理器?

How to detach NSTextView's undo manager from NSDocument?

我有一个不可直接编辑格式的 NSDocument,它是对 XML 中某些内容的描述。 NSWindow 有一个与之关联的设置视图控制器,它可以很好地处理文档中的数据,按预期撤消工作,保存等。现在 NSWindow 中还有一个 NSTextView,用户可以在其中输入一些文本,但不能文档内容的一部分,它仅用作临时文本。当然,我也想支持撤消此文本,因此我在 Interface Builder 中为此 NSTextView 启用了“撤消”复选标记,并且撤消工作正常。

问题来了:修改 NSTextView 时,NSDocument 被标记为脏。因为这是临时文本,所以我不希望用户被唠叨去保存对文档的更改,这实际上不是文档的一部分。

如何从通向 NSDocument 的撤消管理器实例的响应程序链中分离 NSTextView?简单地提供一个新的 NSUndoManager 实例并不能解决它,因为它也沿着响应链上升到 NSDocument。

extension InputViewController: NSTextViewDelegate {
    func undoManager(for view: NSTextView) -> UndoManager? {
        return myUndoManager
    }
}

我很确定您需要覆盖 window 视图控制器的 undoManager 属性,而不是文本字段的委托。

但是,要简单地使您的 document/window 永久不可编辑,您需要做的就是覆盖 documentEdited 属性,这样它总是 returns false,或重写 updateChangeCount,以便它忽略记录更改的请求。

感谢 James Bucanek 关于覆盖 updateChangeCount 的评论,我能够在我的 NSDocument 子类中做这样的事情:

    override func updateChangeCount(_ change: NSDocument.ChangeType) {
        if !suppressChangeCount {
            super.updateChangeCount(change)
        } else {
            suppressChangeCount = false
        }
    }

因此允许 undo/redo 在我的 InputViewController 键码处理程序中工作而不会弄脏文档。