【问题标题】:How to detach NSTextView's undo manager from NSDocument?如何从 NSDocument 中分离 NSTextView 的撤消管理器?
【发布时间】:2020-11-03 07:08:53
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我试过你的代码,它对我有用。代表是否已连接/设置? undoManager(for:) 被调用了吗?请发帖minimal reproducible example
  • 代码没有错,我只是用它来表达我的意思“提供一个新的NSUndoManager实例”
  • 文档没有被标记为脏。只需提供一个新的 NSUndoManager 实例就可以解决它。有什么问题?
  • 好吧,好吧。我重新测试了这个,你瞧,这很好用。我一直都有答案。感谢您坚持推动我这样做。
  • ..但是,它破坏了设置视图控制器的撤消管理器。我真的只想要一个撤消管理器,因此我选择了下面的答案,使用updateChangeCount 覆盖。

标签: macos cocoa nstextview nsdocument


【解决方案1】:

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

但是,要简单地使您的文档/窗口永久不可编辑,您只需覆盖documentEdited 属性,使其始终返回false,或覆盖updateChangeCount,使其忽略记录更改的请求。

【讨论】:

  • 我仍然希望文档在由设置视图控制器编辑时变脏。我想要做的是将临时文本 NSTextView 撤消管理器从使 NSDocument 变脏中分离出来。本质上改变了 NSTextView 的响应者链。
  • 我从来没有尝试过为单个视图(仅文档和窗口)使用撤消管理器,但我怀疑该视图正在从 NSTexFieldNSTextView 获取其撤消管理器而不是代表。 NSResponder 的文档说它“只是在下一个响应者上调用此属性”,因此您可能会拦截窗口上的 undoManager(仅用于调试),设置断点,并查看是否可以跟踪调用链它从哪里来的。这可以让您了解在哪里拦截它。
  • 好吧,从 NSDocument.addWindowController() 的文档中可以看出,发生了什么:“NSDocument 对象在显示所有文档窗口时使用其窗口控制器列表,在撤消或设置窗口编辑状态时重做操作,并修改窗口标题[...]”这意味着任何视图控制器的撤消管理器都将绑定到响应者链中。我仍然对如何排除我在问题中提到的一个视图控制器感到困惑。
  • "或覆盖 updateChangeCount 以便它忽略记录更改的请求。"是的,这就是我要探索的方向。
【解决方案2】:

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

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

因此允许撤消/重做在我的InputViewController 键码处理程序中工作,而不会弄脏文档。

【讨论】:

    猜你喜欢
    • 2014-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-04
    • 1970-01-01
    • 1970-01-01
    • 2016-10-14
    • 1970-01-01
    相关资源
    最近更新 更多