在应用 terminates/window 关闭之前对 NSDocument 进行最后一次更改?

Make one last change to NSDocument before app terminates/window closes?

我有一个基本的基于 NSDocument 的应用程序。我需要在以下时间对文档进行最后一次更改:

  1. 用户关闭文档的window
  2. 用户终止应用程序

为什么?

文档 window 包含一个 NSTextField。通常,在用户按下 Enter 键后(通过 textDidEndEditing(_:)),输入到该文本字段中的文本会提交到文档模型。

假设用户键入了一些文本,但没有按 Enter。相反,他按下 Cmd-W 或 Cmd-Q 来关闭文档 window 或完全终止应用程序。

textDidEndEditing 未被调用,因此我检查文本字段是否包含更改并尝试自己更新文档。

❌ 这就是它变得棘手的地方。以下导致 NSDocument.performActivityWithSynchonousWaiting 上的死锁:

override func viewWillDisappear() {
    super.viewWillDisappear()

    undoManager?.disableUndoRegistration()
    textField.commitEditing() // Updates the model

    document.updateChangeCount(.changeDone)
}

我设法通过不连接到 viewWillDisappear 而是连接到 NSDocument.canClose(withDelegate delegate: Any, shouldClose shouldCloseSelector: Selector?, contextInfo: UnsafeMutableRawPointer?).

来解决僵局

✅ 此代码导致在用户关闭文档时保存更改 window:

override func canClose(withDelegate delegate: Any, shouldClose shouldCloseSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {

    undoManager?.disableUndoRegistration()
    textField.commitEditing() // Updates the model

    updateChangeCount(.changeDone)

    super.canClose(withDelegate: delegate, shouldClose: shouldCloseSelector, contextInfo: contextInfo)
}

.

❓不幸的是,当用户终止应用程序时,不会调用上面的方法。我尝试在 applicationWillTerminate() 中更新我的文档——没有用。我还尝试覆盖 applicationShouldTerminate() 并延迟终止 3 秒。我可以看到文档的 window 被标记为 "edited",但更改未保存。

如何在应用程序终止之前对 NSDocument 进行最后一次更改并自动保存它?

供参考:我认为在应用程序终止时不可能对 NSDocument 进行最后更改。文档架构根本不是那样设计的(参见 https://www.mail-archive.com/cocoa-dev@lists.apple.com/msg107739.html

在应用程序终止时,文档的 windows 已关闭并且 window 控制器已释放。

我最终解决了这个问题,方法是更改​​我的应用程序的设计以在用户键入时记录对文档的更改。我使用 UndoManager 的新实例并手动调用 NSDocument.updateChangeCount(.changeDone) 以将我的更改注册到 undo/redo 链之外。当用户最终通过按 Enter 键提交更改时,我使用文档的撤消管理器来注册更改。