I have a basic NSDocument-based app. I need to make one last change to the document when:
- The user closes the document's window
- The user terminates the app
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?
- Some AppKit functionality automatically disables sudden termination on a temporary basis to ensure data integrity. - NSDocument temporarily disables sudden termination to prevent process killing between the time at which the user has made a change to a document and the time at which the user's change has been written to disk. – MyCometG3 Aug 28 '19 at 22:51