在应用 terminates/window 关闭之前对 NSDocument 进行最后一次更改?
Make one last change to NSDocument before app terminates/window closes?
我有一个基本的基于 NSDocument 的应用程序。我需要在以下时间对文档进行最后一次更改:
- 用户关闭文档的window
- 用户终止应用程序
为什么?
文档 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 键提交更改时,我使用文档的撤消管理器来注册更改。
我有一个基本的基于 NSDocument 的应用程序。我需要在以下时间对文档进行最后一次更改:
- 用户关闭文档的window
- 用户终止应用程序
为什么?
文档 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 键提交更改时,我使用文档的撤消管理器来注册更改。