Reputation: 525
I'm converting an old macOS app to SwiftUI, and I've run into a problem with the new SwiftUI WindowGroup.
The old app is a single window application (basically a glorified timer) and an URL scheme (appname://15) can be used to change the timer.
I've attempted to recreate the old URL Scheme functionality using the onOpenURL method, but whenever the URL Scheme triggers, the app opens a new window and I can't figure out how to stop that from happening.
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL(perform: { url in
print("\(url)") // This is just debug code
})
}.commands {
CommandGroup(replacing: .newItem, addition: { })
}
}
I don't mind if the new version of the app allows multiple timers, but the url scheme is definitely not intended to open up new windows every time it's used.
How do I stop onOpenURL from launching new windows? I'm converting the app specifically to learn SwiftUI, but if it's not possible to do this behavior in SwiftUI, I'm willing to mix and match in some AppKit code.
Upvotes: 21
Views: 5387
Reputation: 6251
The article, "Open window / scene in SwiftUI 2.0 on macOS" shows how to open windows. I took the pieces of it and made it to where it would simply open my window instead of a different one.
var body: some Scene {
WindowGroup {
ContentView()
.handlesExternalEvents(preferring: ["{path of URL?}"], allowing: ["*"]) // activate existing window if exists
.onOpenURL(perform: { url in
print("\(url)") // This is just debug code
})
}.commands {
CommandGroup(replacing: .newItem, addition: { })
}
.handlesExternalEvents(matching: ["{same path of URL?}"]) // create new window if doesn't exist
}
For those wanting to (try to) better understand preferring
and allowing
parameters. Paraphrased from Apple documentation:
preferring
parameter is a Set of strings that are checked to see if they are contained in the targetContentIdentifier
of this view (ContentView
in this case) to see if this view prefers to handle the external event (openURL
in this case) versus another view.
allowing
parameter is a Set of strings that are checked to see if they are contained in the targetContentIdentifier
of this view, allowing the view to handle the event.
Empty Sets are never matched. "*"
are always matched.
Reference: Apple Documentation on handlesExternalEvents(preferring:allowing:)
Upvotes: 29