点击FCM通知跳转至指定UITabBarController页面的问题
问题
使用FCM实现通知功能,应用配置完成且能正常接收通知,也可根据通知携带的数据执行对应操作,但点击通知后无法跳转至指定ViewController,具体问题如下:
- 初始ViewController为
AccessController,用于用户注册或登录,登录成功后通过以下代码跳转至主TabController:
func loginExitoso() { self.performSegue(withIdentifier: "loginExSeg", sender: nil) }
- 在AppDelegate中处理通知点击的代码如下,但调用rootViewController的segue无效果:
extension AppDelegate: UNUserNotificationCenterDelegate { // 其他函数已省略 func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async { let userInfo = response.notification.request.content.userInfo if userInfo["action_location"]! as? String == "horario" { self.window?.rootViewController!.performSegue(withIdentifier: "gotoHusoHorarioSegue", sender: nil) } } }
- 尝试实例化主TabController并设置为rootViewController,出现"无对应segue标识符"的错误,同时状态栏变为黑色;后续通过设置
selectedIndex实现页面跳转,但给LunaHoy控制器的idEntrada赋值后,该参数在viewDidAppear中未生效,需解决此传参问题。
解决方案
一、修复通知点击跳转失效问题
1. 按需处理根控制器类型
当前rootViewController会根据登录状态切换为AccessController或TabController,直接调用segue会因上下文不匹配失效,需先判断根控制器类型再处理:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async { let userInfo = response.notification.request.content.userInfo guard let window = self.window else { return } if userInfo["action_location"] as? String == "horario" { // 已登录状态:直接操作TabController if let tabVC = window.rootViewController as? UITabBarController { tabVC.selectedIndex = 0 // 替换为LunaHoy所在的tab索引 // 获取目标控制器并处理后续逻辑 if let lunaHoyVC = tabVC.selectedViewController as? LunaHoy { // 这里先处理传参,见下文 } } // 未登录状态:先跳转登录页,后续再处理通知逻辑 else if let accessVC = window.rootViewController as? AccessController { accessVC.performSegue(withIdentifier: "loginExSeg", sender: nil) // 可将通知userInfo存入全局变量,登录完成后自动处理跳转和传参 } } }
2. 正确从Storyboard加载TabController
直接实例化TabController会丢失Storyboard中定义的segue和配置,需从Storyboard加载:
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main) guard let tabVC = storyboard.instantiateViewController(withIdentifier: "TabControllerIdentifier") as? UITabBarController else { return } window.rootViewController = tabVC window.makeKeyAndVisible()
注意替换"Main"为你的Storyboard文件名,"TabControllerIdentifier"为TabController在Storyboard中设置的标识符。
二、修复idEntrada传参不生效问题
1. 手动触发页面数据刷新
直接赋值idEntrada时,LunaHoy的viewDidAppear可能已经执行完毕,需手动调用数据加载方法:
在LunaHoy控制器中添加刷新逻辑:
class LunaHoy: UIViewController { var idEntrada: String = "" // 自定义数据刷新方法 func loadDataWithId() { guard !idEntrada.isEmpty else { return } // 根据idEntrada执行数据请求、UI更新等逻辑 } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) loadDataWithId() // 确保页面显示时自动加载数据 } }
然后在通知处理代码中赋值后调用该方法:
if let lunaHoyVC = tabVC.selectedViewController as? LunaHoy { lunaHoyVC.idEntrada = userInfo["idEntrada"] as? String ?? "" lunaHoyVC.loadDataWithId() }
2. 使用通知中心传递参数(适用于复杂层级)
如果控制器层级较深,可通过NotificationCenter传递参数:
在LunaHoy中添加监听:
override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(updateIdEntrada(_:)), name: NSNotification.Name("UpdateLunaHoyId"), object: nil ) } @objc private func updateIdEntrada(_ notification: Notification) { if let id = notification.userInfo?["idEntrada"] as? String { self.idEntrada = id self.loadDataWithId() } } deinit { NotificationCenter.default.removeObserver(self) }
在通知处理代码中发送通知:
NotificationCenter.default.post( name: NSNotification.Name("UpdateLunaHoyId"), object: nil, userInfo: ["idEntrada": userInfo["idEntrada"] as? String ?? ""] )
内容的提问来源于stack exchange,提问作者Mihail Minkov
相关产品推荐
相关产品推荐

