AppDelegate.swift中ViewController调用及推送跳转返回失效问题
解决推送通知打开ChatRoomViewController后返回按钮无响应的问题
我之前也碰到过一模一样的问题,核心原因很明确:直接把ChatRoomViewController设为window的根视图控制器后,它并没有处于导航控制器的视图栈中——导航栏的返回按钮依赖导航栈来定位上一级页面,现在栈里只有它自己,点击自然没有响应。
下面分场景给你梳理正确的实现方案,先从基础导航结构调整开始:
第一步:搭建正确的基础导航框架
首先,把MessengerBox(你的TableViewController)作为UINavigationController的根视图控制器,再将这个导航控制器设为window的根:
// 在AppDelegate的didFinishLaunchingWithOptions中(如果用SceneDelegate就写在对应方法里) let messengerBoxVC = MessengerBox() let navController = UINavigationController(rootViewController: messengerBoxVC) window?.rootViewController = navController window?.makeKeyAndVisible()
这样平时用户点击单元格时,直接push ChatRoomViewController即可,返回按钮会正常工作:
// 在MessengerBox的didSelectRowAt方法内 let chatRoomVC = ChatRoomViewController() // 传递聊天所需参数,比如聊天ID chatRoomVC.chatID = selectedChatID navigationController?.pushViewController(chatRoomVC, animated: true)
第二步:处理推送通知的两种场景
场景1:应用处于后台,点击通知唤醒
在UNUserNotificationCenterDelegate的didReceiveNotificationResponse方法里,获取当前导航控制器,再push对应的ChatRoomViewController:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { // 从通知内容里提取聊天ID等关键参数 let userInfo = response.notification.request.content.userInfo guard let chatID = userInfo["chatID"] as? String else { completionHandler() return } // 获取当前的根导航控制器 guard let rootNav = UIApplication.shared.keyWindow?.rootViewController as? UINavigationController else { completionHandler() return } // 检查栈中是否已有对应ChatRoomVC,避免重复创建 let existingChatVC = rootNav.viewControllers.first { $0 is ChatRoomViewController && ($0 as? ChatRoomViewController)?.chatID == chatID } if let existingChatVC = existingChatVC { // 已有则直接切到该页面 rootNav.popToViewController(existingChatVC, animated: true) } else { // 没有则实例化并push let chatRoomVC = ChatRoomViewController() chatRoomVC.chatID = chatID rootNav.pushViewController(chatRoomVC, animated: true) } completionHandler() }
场景2:应用未运行,点击通知启动
在AppDelegate的didFinishLaunchingWithOptions里,先检查启动参数中的通知信息,再构建完整的导航栈:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // 1. 初始化基础导航结构 let messengerBoxVC = MessengerBox() let navController = UINavigationController(rootViewController: messengerBoxVC) window?.rootViewController = navController window?.makeKeyAndVisible() // 2. 判断是否通过推送通知启动 if let notificationInfo = launchOptions?[.remoteNotification] as? [String: Any], let chatID = notificationInfo["chatID"] as? String { // 实例化ChatRoomVC并推入导航栈(冷启动不需要动画) let chatRoomVC = ChatRoomViewController() chatRoomVC.chatID = chatID navController.pushViewController(chatRoomVC, animated: false) } return true }
这样处理后,不管是从应用内点击单元格,还是从推送通知进入,ChatRoomViewController都处于完整的导航栈中,点击返回按钮就能正常回到MessengerBox页面了。
内容的提问来源于stack exchange,提问作者kyungjun min
相关产品推荐
相关产品推荐

