Swift无Storyboard环境下如何在userNotificationCenter中pushViewController
嘿,我来帮你搞定这个点击推送跳转导航控制器的问题!你的现有代码已经有了开头,但核心是要正确获取当前应用的导航控制器实例,而不是新建一个——不然会脱离原有的页面栈,导致跳转逻辑混乱。下面是完整的实现方案:
核心逻辑梳理
- 先拿到应用的主窗口,确保能访问到根视图控制器
- 根据你的根控制器结构(可能是导航控制器或标签栏控制器),找到当前活跃的导航控制器
- 实例化目标页面,按需传递推送里的自定义数据
- 把目标页面push到已有导航栈中,同时确保窗口处于活跃状态(处理应用从后台唤醒的场景)
完整代码实现
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { // 1. 获取当前应用的主窗口 guard let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else { completionHandler() return } // 2. 找到当前活跃的UINavigationController var targetNavController: UINavigationController? // 情况1:根控制器直接是导航控制器 if let rootNav = window.rootViewController as? UINavigationController { targetNavController = rootNav } // 情况2:根控制器是标签栏控制器,取当前选中项的导航控制器 else if let tabBarVC = window.rootViewController as? UITabBarController { targetNavController = tabBarVC.selectedViewController as? UINavigationController } // 如果没找到可用的导航控制器,直接结束流程 guard let navVC = targetNavController else { completionHandler() return } // 3. 实例化你要跳转的目标页面(替换成你的实际控制器类) let destinationVC = YourTargetViewController() // 4. 从推送的userInfo里提取自定义数据,传递给目标页面 let userInfo = response.notification.request.content.userInfo // 示例:假设推送里有个"page_id"的自定义字段 if let pageId = userInfo["page_id"] as? String { destinationVC.pageId = pageId } // 5. 执行跳转操作 navVC.pushViewController(destinationVC, animated: true) // 6. 确保窗口处于活跃状态(处理应用从后台唤醒的情况) window.makeKeyAndVisible() // 一定要调用completionHandler,通知系统处理完成 completionHandler() }
关键注意事项
- 不要新建导航控制器:你代码里的
SomeNavigationController()是个误区,应该复用应用已有的导航栈,否则会导致页面栈混乱,用户返回时找不到之前的页面 - 适配不同根控制器结构:如果你的根控制器是其他类型(比如自定义容器控制器),需要调整获取导航控制器的逻辑,确保能拿到当前活跃的导航实例
- 代理设置:确保在
AppDelegate或SceneDelegate里设置UNUserNotificationCenter.current().delegate = self,并且你的类遵循UNUserNotificationCenterDelegate协议 - 处理后台唤醒:加上
window.makeKeyAndVisible()可以确保应用从后台唤醒时,窗口能正常显示跳转后的页面
内容的提问来源于stack exchange,提问作者UK4
相关产品推荐
相关产品推荐

