首页 > 解决方案 > 在应用程序终止/窗口关闭之前对 NSDocument 进行最后一次更改?

问题描述

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

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

为什么?

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

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

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?).

✅ 此代码会在用户关闭文档窗口时保存更改:

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 秒。我可以看到文档的窗口被标记为“已编辑”,但没有保存更改。

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

标签: cocoanstextfieldnsdocumentnsapplicationnsapplication-delegate

解决方案


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

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

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


推荐阅读