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

自定义URL Scheme处理时,scene(_:willConnectTo:)中rootVC为空如何启动视图控制器?

解决冷启动时Widget Deep Link跳转失败的问题

冷启动时scene(_:willConnectTo:)的调用时机早于根视图控制器初始化,导致window?.rootViewController为空,无法执行跳转。可以通过延迟处理Deep Link的方式解决,具体步骤如下:

步骤1:在SceneDelegate中添加待处理URL属性

在SceneDelegate类中新增可选URL属性,用于暂存冷启动时收到的Deep Link:

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?
    // 暂存冷启动时的Deep Link
    private var pendingDeepLinkURL: URL?
    
    // ... 其他已有方法
}

步骤2:修改冷启动时的URL处理逻辑

在scene(_:willConnectTo:)中,不再直接调用handleIncomingURL,而是将URL存入待处理属性:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = scene as? UIWindowScene else { return }
    
    // 手动初始化窗口和根视图控制器(若项目依赖Storyboard自动加载,可跳过此段)
    window = UIWindow(windowScene: windowScene)
    let rootVC = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()
    window?.rootViewController = rootVC
    window?.makeKeyAndVisible()
    
    // 暂存Deep Link URL
    if let url = connectionOptions.urlContexts.first?.url {
        pendingDeepLinkURL = url
    }
}

步骤3:在应用激活后处理待跳转URL

实现sceneDidBecomeActive方法,在应用完全激活、根视图控制器就绪时,处理暂存的Deep Link:

func sceneDidBecomeActive(_ scene: UIScene) {
    if let url = pendingDeepLinkURL {
        handleIncomingURL(url)
        // 处理完成后清空属性,避免重复跳转
        pendingDeepLinkURL = nil
    }
}

补充:确保handleIncomingURL逻辑兼容两种场景

原有handleIncomingURL逻辑无需修改,后台恢复时scene(_:openURLContexts:)会直接调用它,冷启动时则在sceneDidBecomeActive中延迟调用(此时rootViewController已存在):

private func handleIncomingURL(_ url: URL) {
    guard url.scheme == "widget" else { return }
    
    guard let rootViewController = window?.rootViewController else {
        print("no rootViewController")
        return
    }
    
    // 关闭所有弹出的视图控制器
    rootViewController.dismiss(animated: false)
    
    let greenViewController = GreenViewController.instanceFromMainStoryBoard()
    rootViewController.present(greenViewController, animated: true)
}

额外说明

若项目通过Storyboard自动初始化窗口和根视图控制器(即Info.plist中配置了UISceneStoryboardFile),无需手动创建window和rootVC,只需在sceneDidBecomeActive中检查pendingDeepLinkURL即可,系统已完成根视图控制器的初始化。


内容的提问来源于stack exchange,提问作者Cheok Yan Cheng

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 09:10:44