通过自定义URL Scheme启动App时无窗口的问题解决求助
解决SwiftUI App中URL Scheme触发时无窗口显示的问题
问题分析
当App处于关闭(点击窗口X按钮)或未启动状态时,通过URL Scheme唤起App后,NSApplication.shared.windows.first返回nil,无法显示窗口。这是因为SwiftUI的WindowGroup仅在App首次启动时自动创建窗口,当窗口被关闭或App完全退出后,需要手动触发窗口的重建逻辑。
解决方案
1. 触发场景激活创建窗口
在处理URL事件的方法中,当检测到无可用窗口时,调用NSApplication.shared.requestSceneSessionActivation接口,触发WindowGroup创建新窗口。
2. 确保App处于激活状态
唤起时先激活App,保证后续窗口创建操作能正常执行,同时所有UI操作必须在主线程完成。
修改后的完整代码
AppDelegate实现
class AppDelegate: NSObject, NSApplicationDelegate { var appPageManager: PageManager = PageManager() @MainActor @objc func handleGetURLEvent(_ event: NSAppleEventDescriptor, withReplyEvent: NSAppleEventDescriptor) { if let window = NSApplication.shared.windows.first { print("check window is miniaturized: \(window.isMiniaturized)") if window.isMiniaturized { appPageManager.text = "窗口已最小化,正在恢复" window.deminiaturize(nil) } else { appPageManager.text = "窗口处于正常状态" } } else { appPageManager.text = "窗口已关闭,正在创建新窗口" print("window is closed, triggering new window creation") // 激活App并触发新窗口创建 NSApp.activate(ignoringOtherApps: true) if let session = NSApplication.shared.openSessions.first { NSApplication.shared.requestSceneSessionActivation(session, userActivity: nil, options: .activateAllWindows) { _ in print("新窗口创建成功") } } else { // 无现有会话时直接请求激活新场景 NSApplication.shared.requestSceneSessionActivation(nil, userActivity: nil, options: []) { _ in print("新场景会话已激活") } } } if let urlString = event.forKeyword(AEKeyword(keyDirectObject))?.stringValue { guard let url = URL(string: urlString) else { print("URL scheme, invalid URL") return } // 处理URL内容,更新页面状态 appPageManager.text = "收到URL: \(url.absoluteString)" } } func applicationWillFinishLaunching(_ notification: Notification) { print("event: \(#function)") NSApplication.shared.setActivationPolicy(.regular) NSApplication.shared.activate(ignoringOtherApps: true) let appleEventManager = NSAppleEventManager.shared() appleEventManager.setEventHandler( self, andSelector: #selector(handleGetURLEvent(_:withReplyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL) ) } }
主App结构优化
import SwiftUI import AppKit import LocalAuthentication class PageManager: ObservableObject { @Published var text: String = "hello world" } @main struct url_scheme_testApp: App { @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate @StateObject private var pageManager = PageManager() var body: some Scene { WindowGroup { Text("message:\(pageManager.text)") .environmentObject(pageManager) } } init() { // 同步PageManager到AppDelegate,保证数据一致性 appDelegate.appPageManager = pageManager } }
关键说明
requestSceneSessionActivation是SwiftUI场景架构下重建窗口的标准方式,会自动触发WindowGroup实例化新窗口。- 所有涉及UI的操作必须标记
@MainActor,确保在主线程执行,避免线程安全问题。 - URL解析后的业务逻辑可以直接更新
PageManager的属性,SwiftUI会自动刷新视图内容。
内容的提问来源于stack exchange,提问作者whatai cheng
相关产品推荐
相关产品推荐

