UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Close all windows on quit

Forums > macOS

I'm writing an app that has a UI like XCode where the initial window presents options for opening/creating a file and has a list of the recently opened files. That all looks fine and works... except, if I quit my app with documents open and re-open the app, the documents will reopen in their windows. I don't want that to happen, I want my initial window to come up and for the user to have to decide whether to reopen their documents.

Is there a way to close all windows when the user quits my app? Or, can I stop macOS from saving/restoring my window state. I know there is a seting I can set for the whole of macOS, but I want to be able to change the default behaviour for just my application.

I'm considering taking over the Quit menu to deal with closing windows and asking the user whether they want to save their files. Don't know if that's a good place to do it or not, but it's what I would have done on Windows.

Thank you.

2      

It's a bit rubbish and not very SwiftUI-ish, but I seem to have got something working. I've had to code:

 .onReceive(NotificationCenter.default.publisher(for: NSApplication.willTerminateNotification), perform: { _ in }

and

.onReceive(NotificationCenter.default.publisher(for: NSWindow.willCloseNotification)) { output in 

guard let window = output.object as? NSWindow else { return }}

The first gets sent to me when the app quits and the second is sent every time a window closes (any window). In the windowWillCloseNotification, I need to check that window.windowNumber matches my current window. Luckily, I have the window number using HostingWindowFinder.

Once in my code, I can code an NSAlert to ask whether the user wants to save their data. Since that's shown modally, the app waits for a response.

For the record, HostingWindowFinder is a useful bit of code I found somewhere in StackOverflow. It returns me a reference to the window that the SwiftUI view is hosted in.

struct HostingWindowFinder: NSViewRepresentable {
    var callback: (NSWindow?) -> Void

    func makeNSView(context: Self.Context) -> NSView {
        let view = NSView()
        DispatchQueue.main.async { [weak view] in
            self.callback(view?.window)
        }
        return view
    }
    func updateNSView(_ nsView: NSView, context: Context) {}
}

2      

I am fairly certain that this could be done via the NSApplication delegate. For example, if you look at Apple's documentation, (see link below) there is an optional delegate method called applicationShouldHandleReopen. If this method returns false, then the app will not attempt to reopen windows when activated.

This may or may not work in the context of application launch; you'd have to experiment. To implement a NSApplication delegate within the context of a SwiftUI app, I believe you need to use a NSApplicationDelegateAdaptor wrapper. See second link below.

Dave

https://developer.apple.com/documentation/appkit/nsapplicationdelegate/1428638-applicationshouldhandlereopen

https://developer.apple.com/documentation/swiftui/nsapplicationdelegateadaptor

2      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.