You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 01:18:32