Why is restoreWindow(withIdentifier:state:) called after applicationDidFinishLaunching(_:)?

32 Views Asked by At

The NSWindowRestoration protocol has two methods, it is actually one but you must choose either a synchronous method using a completion handler or an asynchronous method.

Synchronous

@MainActor static func restoreWindow(withIdentifier identifier: NSUserInterfaceItemIdentifier, state: NSCoder, completionHandler: @escaping (NSWindow?, Error?) -> Void)

Asynchronous

@MainActor static func restoreWindow(withIdentifier identifier: NSUserInterfaceItemIdentifier, state: NSCoder) async throws -> NSWindow

I wanted to use the asynchronous method because I have adopted Swift concurrency in the rest of my app and it is a modern API. I also want to be consistent and avoid completion handlers or synchronous methods. I've been having many problems getting it to work correctly, especially the timing.

What I found out is that this method is called after applicationDidFinishLaunching(_:) whereas the synchronous method is called before applicationDidFinishLaunching(_:). So this explains why I was getting duplicated windows.

What I do at the end of applicationDidFinishLaunching(_:) is check if my windows array is empty and if it is then make a window.

Is this a normal expected behaviour?

I noticed in Xcode Version 15.2 (15C500b), the compiler produces a warning about the asynchronous method:

Non-sendable type 'NSCoder' in parameter of the protocol requirement satisfied by main actor-isolated static method 'restoreWindow(withIdentifier:state:)' cannot cross actor boundary

I thought maybe this explains why the asynchronous method is called late? I tried making it compliant by doing this:

extension NSCoder: Sendable {}

Then the warning said:

Conformance to 'Sendable' must occur in the same source file as class 'NSCoder'; use '@unchecked Sendable' for retroactive conformance

So I did this:

extension NSCoder: @unchecked Sendable {}

And that didn't help.

Is this something that Apple needs to address (should I file a feedback?) or is it working as expected?

Why would you want restoreWindow(withIdentifier:state:) to be called late, especially after applicationDidFinishLaunching(_:), where you are supposed to setup a window? How are you supposed to know if you are to create a new window or let the system restore windows?

0

There are 0 best solutions below