Search code examples
swiftappkitmac-catalyst

Create new UINSWindow from Catalyst


In my Catalyst app I'm creating a second window using the following code:

let userActivity = NSUserActivity(activityType: "window2")
UIApplication.shared.requestSceneSessionActivation(nil, userActivity: userActivity, options: nil) { error in
    print("error: \(error)")
}

This creates a new window, but it's of type NSPopoverWindow and not UINSWindow as I expected.

I need to change the properties of the underlying NSWindow object and I have create a MacOS Bundle to interface AppKit as described in this fine blogpost: Mac Catalyst: Interfacing Between UIKit and AppKit without Private APIs in Swift

So, is it possible to create a new UINSWindow from Catalyst, or do I need to create it with AppKit from my MacOS Bundle?


Solution

  • Looks like both a new NSPopoverWindow and a new UINSWindow are created when the new scene is activated, and both are added to the NSApplication.sharedApplication.windows array. As NSPopoverWindow doesn't have an uiWindows property, the code from the blogpost crashed. Checking the object type solved my problem:

    private func nsWindow(from window: UIWindow) -> AnyObject? {
        guard let nsWindows = NSClassFromString("NSApplication")?.value(forKeyPath: "sharedApplication.windows") as? [AnyObject] else { return nil }
        for nsWindow in nsWindows {
            if !String(describing: nsWindow).contains("UINSWindow") {
                continue
            }
            
            let uiWindows = nsWindow.value(forKeyPath: "uiWindows") as? [UIWindow] ?? []
            if uiWindows.contains(window) {
                return nsWindow
            }
        }
        return nil
    }