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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:03:06