iOS Swift:AppDelegate中self.window?.rootViewController报错 不删SceneDelegate如何实现推送跳转
适配SceneDelegate的推送跳转实现方案
崩溃原因
iOS 13 引入多场景管理机制后,窗口实例的管理逻辑从AppDelegate迁移到了SceneDelegate,默认情况下AppDelegate的window属性不会被初始化,所以你直接访问self.window?.rootViewController会得到nil值,强制解包就会触发Swift runtime failure: force unwrapped a nil value崩溃。
解决代码
不需要删除SceneDelegate相关文件,只需要修改根控制器的获取逻辑,从当前活跃的场景中取窗口实例即可,修改后的完整代码如下:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { print("userNotificationCenter didReceive") defer { completionHandler() } guard response.actionIdentifier == UNNotificationDefaultActionIdentifier else { return } let storyboard = UIStoryboard(name: "Main", bundle: nil) let destinationVC = storyboard.instantiateViewController(withIdentifier: "MyPage") as! PageViewController // 适配Scene机制,从活跃场景中获取根导航控制器 guard let windowScene = UIApplication.shared.connectedScenes .filter({ $0.activationState == .foregroundActive || $0.activationState == .foregroundInactive }) .first as? UIWindowScene, let navigationController = windowScene.windows.first?.rootViewController as? UINavigationController else { return } navigationController.pushViewController(destinationVC, animated: false) UNUserNotificationCenter.current().removeAllDeliveredNotifications() }
特殊场景适配
- 如果你的App根控制器是
UITabBarController,需要先拿到UITabBarController实例,再取当前选中的导航控制器执行跳转 - 如果当前页面有模态弹出的控制器,需要先遍历找到最顶层的展示控制器,再执行push或者present操作
内容的提问来源于stack exchange,提问作者Punreach Rany
相关产品推荐
相关产品推荐

