admin管理员组

文章数量:1410682

I created an app that uses WindowGroup and utilizes handlesExternalEvents to manage external URL opening events, preventing WindowGroup from opening a new window again.

Everything is fine. The window group does not trigger a new window, and view successfully receives the openURL event. The only issue is that when the app is launched by opening a file, the window group does not automatically open because of handlesExternalEvents.

import SwiftUI

import os.log

@main
struct HandleExternalEventsDemoApp: App {
#if os(macOS)
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
#elseif os(iOS)
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
#endif
        
    let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "HandleExternalEventsDemoApp")
    
    var body: some Scene {
        WindowGroup {
            VStack {
                Image(systemName: "globe")
                    .imageScale(.large)
                    .foregroundStyle(.tint)
                Text("Hello, world!")
            }
            .padding()
            .handlesExternalEvents(preferring: ["MainWindowGroup"], allowing: ["*"])
            .onOpenURL { url in
                logger.info("on open url: \(String(describing: url), privacy: .public)")
            }
        }
        // will not open a window on startup by open a file
        .handlesExternalEvents(matching: ["MainWindowGroup"])
    }
}

#if os(macOS)
import AppKit
class AppDelegate: NSObject, NSApplicationDelegate {
    var openedURLs: [URL] = []
    var didLaunched = false
    let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "AppDelegate")
    
    func application(_ application: NSApplication, open urls: [URL]) {
        // unhandled urls...
        logger.info("\(#function), urls: \(urls, privacy: .public)")
    }
}

#elseif os(iOS)
import UIKit
class AppDelegate: NSObject, UIApplicationDelegate {

}
#endif

My question is that is there any solution to solve this?

handlesExternalEvents(matching:) tells that Specifies the external events for which SwiftUI opens a new instance of the modified scene. from document.

If there is no window in the WindowGroup, even though the WindowGroup scene exists, there will be nothing to handle the ExternalEvents.

I created an app that uses WindowGroup and utilizes handlesExternalEvents to manage external URL opening events, preventing WindowGroup from opening a new window again.

Everything is fine. The window group does not trigger a new window, and view successfully receives the openURL event. The only issue is that when the app is launched by opening a file, the window group does not automatically open because of handlesExternalEvents.

import SwiftUI

import os.log

@main
struct HandleExternalEventsDemoApp: App {
#if os(macOS)
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
#elseif os(iOS)
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
#endif
        
    let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "HandleExternalEventsDemoApp")
    
    var body: some Scene {
        WindowGroup {
            VStack {
                Image(systemName: "globe")
                    .imageScale(.large)
                    .foregroundStyle(.tint)
                Text("Hello, world!")
            }
            .padding()
            .handlesExternalEvents(preferring: ["MainWindowGroup"], allowing: ["*"])
            .onOpenURL { url in
                logger.info("on open url: \(String(describing: url), privacy: .public)")
            }
        }
        // will not open a window on startup by open a file
        .handlesExternalEvents(matching: ["MainWindowGroup"])
    }
}

#if os(macOS)
import AppKit
class AppDelegate: NSObject, NSApplicationDelegate {
    var openedURLs: [URL] = []
    var didLaunched = false
    let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "AppDelegate")
    
    func application(_ application: NSApplication, open urls: [URL]) {
        // unhandled urls...
        logger.info("\(#function), urls: \(urls, privacy: .public)")
    }
}

#elseif os(iOS)
import UIKit
class AppDelegate: NSObject, UIApplicationDelegate {

}
#endif

My question is that is there any solution to solve this?

handlesExternalEvents(matching:) tells that Specifies the external events for which SwiftUI opens a new instance of the modified scene. from document.

If there is no window in the WindowGroup, even though the WindowGroup scene exists, there will be nothing to handle the ExternalEvents.

Share Improve this question edited Mar 6 at 8:59 Chocoford asked Mar 6 at 6:36 ChocofordChocoford 3212 silver badges10 bronze badges 2
  • Opening a file is also opening a URL. So what kind of URLs do you want to open a new window, and what kind of URLs do you not want to open a new window? – Sweeper Commented Mar 6 at 8:23
  • @Sweeper You're right, but the app that opens via open URLs doesn't launch a window, which prevents me from implementing measures to make the handler attached to the view work. In fact, I believe that opening the app should trigger a window, even if it's initiated through URLs. – Chocoford Commented Mar 6 at 8:52
Add a comment  | 

1 Answer 1

Reset to default 0

Finally I figured out. Thanks to GPT. The point is conditions is important. I ignored it before...

So once I replace my code

  • .handlesExternalEvents(matching: ["MainWindowGroup"]) to .handlesExternalEvents(matching: ["*"])
  • .handlesExternalEvents(preferring: ["MainWindowGroup"], allowing: ["*"]) to .handlesExternalEvents(preferring: ["*"], allowing: ["*"])

It works!


Here is the answer by GPT

SwiftUI’s handlesExternalEvents(matching:) method takes a set of Strings that indicate which external event URLs your Scene can handle. Each string in this set can be:

  • A path or domain pattern matching your universal links.
  • A custom scheme (e.g. myapp://somePath).
  • A wildcard * to accept all URLs.

When an external event (like opening a universal link or a custom scheme) arrives, SwiftUI will look for a Scene whose handlesExternalEvents(matching:) conditions match the incoming URL. If a match is found, that Scene (and its view hierarchy) becomes active to handle the event.

Here’s how you can use handlesExternalEvents(matching:) in SwiftUI when you need to handle external URLs:

Matching a specific scheme or path

If your app registers a custom scheme (e.g., myapp://detail), you can specify that in the set:

WindowGroup {
    ContentView()
}
.handlesExternalEvents(matching: ["myapp://detail"])

This scene will be triggered when an external event with the URL myapp://detail is opened.

Matching specific Universal Links

Suppose your app supports Universal Links through https://www.example. You can match particular paths:

WindowGroup {
    ContentView()
}
.handlesExternalEvents(matching: ["www.example/somePath", "www.example/anotherPath"])

This will handle external openings to https://www.example/somePath or https://www.example/anotherPath.

Matching all external events

If you want this scene to handle every URL your app can open, you can specify:

WindowGroup {
    ContentView()
}
.handlesExternalEvents(matching: ["*"])

The * matches all paths, so this is the key if you want to handle all URLs in one place. This solves the issue of having to specify each possible path or scheme individually—use ["*"] to capture everything.

Important: Make sure you’ve set up your URL Types (for custom schemes) or Universal Links properly in your Xcode project (e.g., in Info.plist or via Associated Domains) so that iOS knows your app can handle these links.

本文标签: swiftWindowGroup not opened when app is launched by opening fileStack Overflow