I have a warning dialog from a MacOS application's AppDelegate that needs to be updated with new information. When the new information is available, I want to programmatically dismiss the old dialog and present the new one. I have tried this two ways, both with problems:
Using
alert.runModal()If I use the above, a modal is presented as desired. I can then dismiss the dialog later with
lockWarningModal.window.close(), it works to make the old dialog disappear, but it freezes the UI, so I can no longer interact with it. I am guessing this is becausealert.runModal()is synchronous, and the main thread is still blocked. However, I don't know how to release this.Using
alert.beginSheetModal(for: NSApplication.shared.windows.last!) { (response) in }If I use the above and dismiss the dialog with
NSApplication.shared.windows.last!.endSheet(alert.window), then this solves the UI freeze problem. However, the dialog is attached to the main application window and is not brought to the front as a modal.
How can I achieve a modal dialog that is programmatically dismissible?
You can't stop a model event loop (or alert sheet) by simply closing its window. In fact, using the modern
NSAlertAPI, you should never have to close or order out the window—the framework handles this for you.For an alert started with
runModal()useNSApplication'sabortModal(),stopModal(), orstopModal(withCode:). AfterrunModal()returns, send the alert window anorderOut(nil)to remove it.For an alert sheet that executes a completion block afterwards, use
NSWindow'sendSheet(_)orendSheet(_:returnCode:). The alert will be automatically removed after your completion block executes.