Reputation: 6947
I have a basic NSDocument-based app. I need to make one last change to the document when:
Why?
The document window contains an NSTextField. Usually text entered into this text field is committed to the document's model after the user presses Enter (via textDidEndEditing(_:)
).
Let's assume the user typed some text, but does not press Enter. Instead he presses Cmd-W or Cmd-Q to close the document window or terminate the app altogether.
textDidEndEditing
is not called so I check if the text field contains changes and try to update the document myself.
❌ Here is where it gets tricky. The following results in a deadlock on NSDocument.performActivityWithSynchonousWaiting
:
override func viewWillDisappear() {
super.viewWillDisappear()
undoManager?.disableUndoRegistration()
textField.commitEditing() // Updates the model
document.updateChangeCount(.changeDone)
}
I managed to work around the deadlock by not hooking into viewWillDisappear
, but into NSDocument.canClose(withDelegate delegate: Any, shouldClose shouldCloseSelector: Selector?, contextInfo: UnsafeMutableRawPointer?)
.
✅ This code causes the changes to be saved when the user closes the document 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)
}
.
❓Unfortunately, the above is not called when the user terminates the app. I tried updating my document in applicationWillTerminate()
-- did not work. I also tried overriding applicationShouldTerminate()
and delaying termination for 3 seconds. I can see the document's window being marked as "edited", but changes are not saved.
How can I make a last change to NSDocument right before the app terminates and have it saved automatically?
Upvotes: 0
Views: 272
Reputation: 6947
For reference: I don't think it is possible to make a last change to NSDocument
while the app is being terminated. The document architecture is simply not designed that way (see https://www.mail-archive.com/[email protected]/msg107739.html)
At the time the app is terminating, the document's windows have been closed and window controllers released.
I eventually solved this problem by changing the design of my app to record changes to the document as the user types. I use a new instance of UndoManager
and manually call NSDocument.updateChangeCount(.changeDone)
to register my changes out of the undo/redo chain. When the user finally commits changes by pressing Enter, I use the document's undo manager to register the change.
Upvotes: 0