How to Open a Window in SwiftUI
I’d like to show a second window with different content in a SwiftUI app on macOS. I can’t find any documentation on this.
Malcolm Hall (tweet, forum):
In your
ContentView
create a button and open a URL for your app and another View e.g.Viewer
to be shown in the window we will open[…][…]
In your
App
add anotherWindowGroup
for your viewer and set it to enable handling of external launch events (an internal event in our case).[…]
Now in Project->Info->URL Types type in myappname in the URL Schemes field (and the identifier field too) to register our app with the system.
Is that a workaround? That’s a workaround for missing API, right? 😳
No, its a declarative state-driven API that handles the reason why you would want a new window. You aren’t going to get an imperative open window in SwiftUI because that’s not how it is designed.
I’m not convinced this is designed. It’s more like something that happens, but doesn’t really is well thought for the scenario where the app needs to open multiple windows. URL cannot be the way. It’s missing window state management. Windows are hierarchical. This is not.
It’s great that there is a way to do this without calling into AppKit, but using URLs seems gross.
A common trick is to use an
NSViewRepresentable
to get underlyingview.window
and attach this to our SwiftUI view[…]
For a common macOS SwiftUI app with a search bar on the toolbar and a normal settings screen, here’s how I usually do
Setup NSWindow programmatically
Previously:
Update (2022-07-12): Natalia Panferova (tweet):
In macOS 13 we finally have a way to programmatically present a window in SwiftUI. We can call the new openWindow action from the environment and pass it a scene id or a value.
Previously:
4 Comments RSS · Twitter
Comedy like this reaffirms confidence in the almost total lack of attention that I've paid to SwiftUI since its debut.
I actually think it is only slightly wrong, instead of a URL, it should be a NSUserActivity. But those and URLs are semantically almost the same.
And yes, there is always AppKit. Which just works for that, not sure why people don't just use it? It's a feature not a bug that it can be used.
The worse thing IMO is that despite moving regular restoration to NSUserActivities in UIKit, which makes sense, is that SwiftUI only has @SceneState and no way for controllers to get access to that, w/o hack-patching things in. I.e. you don't get access to a scene.
Is the discussion there suggesting that SwiftUI was effectively made with the assumption that all apps would be contained within a single parent window?
We've seen what happens in, I suspect Catalyst apps, where when you have multiple windows from a single app open, moving the parent window on screen, also moves all the child windows (but not the reverse) as if they're all on a single sheet of glass.
A lot of recent UI frameworks seem to suffer this "we've mostly designed this with mobile in mind so multiple windows are an afterthought" syndrome. Xamarin Forms, Electron, Windows App SDK, etc. all shipped with limited multiple-window support.
What a world.