SwiftUI macOS app with `App` protocol deep linking opens new app instance

Viewed 702

This is in a SwiftUI macOS app using the new App protocol and @main.

Usage flow:

  • User launches app and clicks a button which opens a particular webpage
  • Webpage eventually redirects to the app's URL scheme, opening the app and invoking onOpenURL(_:)

Expected behaviour: The deep link is sent to the existing, currently open app instance

Actual behaviour: A new app instance is launched, causing two instances of the app to be active

Note: There isn't really any code to add since the problem is just dependent on adding a URL scheme to the app and having a webpage go to it.

1 Answers

onOpenURL(_:) is not actually launching a new app instance, it is creating a new window within the existing instance. The documentation would suggest this only happens on macOS (because iOS only supports a single window).

You need to use the .handlesExternalEvents(preferring:allowing:) modifier on a higher order view. Calling handlesExternalEvents will override the default behaviour which is what is creating the new window in your app on macOS. Something like:

@main
struct myApp: App {    
    var body: some Scene {
        WindowGroup {
            ContentView()
            .handlesExternalEvents(preferring: ["myscheme"], allowing: ["myscheme"])
        }
    }
}

An then in a child view (e.g. ContentView()):

var body: some View {
    VStack {
        // your UI
    }
    .onOpenUrl{ url in
        // do something with the deep link url
    }
}
Related