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

使用BlackBerry Dynamics SDK时iOS 13应用如何访问rootViewController?

解决BlackBerry Dynamics SDK集成后Root View Controller访问异常问题

嘿,我碰到过类似的SDK接管window层级的坑,这就帮你理清楚问题出在哪以及怎么修复!

问题到底出在哪?

BlackBerry Dynamics SDK的GDiOS.sharedInstance().authorize()方法会完全接管你的应用window层级——它会创建自己的内部UIViewController作为root,用来处理身份验证、安全容器初始化这些流程。这就是为什么你在release模式下看到的root不是你设置的HomeController,而是一个陌生的UIViewController,自然会触发"view is not in the window hierarchy"的错误,因为这个SDK创建的控制器并没有在当前显示的window层级里。

另外你原来的代码在debug模式下手动创建window并设置root,但release模式下依赖storyboard的初始控制器,同时SDK的授权操作会干扰这个初始化流程,进一步搞乱了界面层级。

正确的处理方案

1. 等SDK授权完成后再设置你的根控制器

BlackBerry Dynamics会通过代理回调通知你授权完成,你要在这个时机再设置自己的根控制器,确保SDK初始化完后再接管界面:

首先完善你的XXXGDiOSDelegate,实现授权成功的回调(具体方法名参考SDK文档,通常是didAuthorize):

class XXXGDiOSDelegate: NSObject, GDiOSDelegate {
    static let sharedInstance = XXXGDiOSDelegate()
    weak var appDelegate: AppDelegate?
    
    func didAuthorize(_ error: Error?) {
        guard error == nil else {
            // 这里处理授权失败的逻辑,比如弹提示
            print("BlackBerry授权失败: \(error!)")
            return
        }
        
        // 授权成功,设置我们自己的根控制器
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let homeController = storyboard.instantiateViewController(withIdentifier: "HomeController") as! HomeController
        
        // 获取SDK管理的window(此时window已经被SDK初始化了)
        if let window = UIApplication.shared.windows.first {
            window.rootViewController = homeController
            window.makeKeyAndVisible()
        }
        
        // 初始化那些需要保留状态的ViewController,存在AppDelegate里
        appDelegate?.setupPersistentViewControllers()
    }
}

然后修改AppDelegate的didFinishLaunchingWithOptions,只负责初始化SDK,不再直接设置root:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // 先初始化BlackBerry Dynamics的代理和授权
    XXXGDiOSDelegate.sharedInstance.appDelegate = self
    GDiOS.sharedInstance().authorize(XXXGDiOSDelegate.sharedInstance)
    
    // Debug模式下跳过SDK授权,直接设置根控制器
    #if DEBUG
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let homeController = storyboard.instantiateViewController(withIdentifier: "HomeController") as! HomeController
        window = UIWindow()
        window?.rootViewController = homeController
        window?.makeKeyAndVisible()
        setupPersistentViewControllers()
    #endif
    return true
}

// 单独抽方法初始化需要保留状态的VC
func setupPersistentViewControllers() {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    // 这里把你需要保留状态的VC都初始化好存在AppDelegate的属性里
    uploadController = storyboard.instantiateViewController(withIdentifier: "UploadController") as! UploadController
    // 比如其他VC:profileController = ... 以此类推
}

// 修改getViewController方法,直接返回预初始化的实例
func getViewController(viewController: VCType) -> UIViewController {
    switch viewController {
    case .Uploads:
        return uploadController!
    // 其他VC的case补充在这里
    }
}

2. 跳转时确保拿到正确的活跃控制器

在你的跳转代码里,不要硬怼UIApplication.shared.windows.first!.rootViewController,而是先确认这个控制器确实在window层级里,或者用当前显示的控制器来present:

@objc func onMenuItemUploadsTap(_ sender: UIView) {
    self.dismiss(animated: false) { [weak self] in
        guard let self = self else { return }
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        let vc = appDelegate.getViewController(viewController: .Uploads)
        vc.modalPresentationStyle = .fullScreen
        
        // 先尝试用有效的root控制器present
        if let rootVC = UIApplication.shared.windows.first?.rootViewController, rootVC.view.window != nil {
            rootVC.present(vc, animated: true)
        } else {
            //  fallback:如果root不可用,用当前控制器来present
            self.present(vc, animated: true)
        }
    }
}

几个额外的注意点

  • 别再依赖storyboard的"Is Initial View Controller"设置了,SDK会直接覆盖它,手动用代码设置根控制器更可靠。
  • 所有需要保留状态的ViewController必须在SDK授权成功后再初始化,这样它们的生命周期才会在SDK的安全容器环境下正常运行。
  • 测试release模式时,务必检查SDK的配置(比如entitlements文件、Provisioning Profile)是否正确,很多时候SDK初始化失败也会导致界面异常。

内容的提问来源于stack exchange,提问作者Schnemar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:16:13