技术求助:导航栈中间推入ViewController及App Delegate通知跳转方法
iOS导航跳转常见问题解决方案
嘿,我来帮你搞定这两个iOS开发里的导航问题,都是日常开发中很实用的场景,直接上干货:
1. 在导航控制器的导航栈中间插入任意ViewController
导航控制器的导航栈本质上是一个viewControllers数组,我们可以直接修改这个数组,把新的ViewController插入到任意位置。举个具体的例子:假设当前导航栈是 VC1 -> VC2 -> VC3,我们想在VC2和VC3之间插入一个CustomVC,代码可以这么写:
// 获取当前导航栈的视图控制器数组 guard let navController = self.navigationController else { return } var currentStack = navController.viewControllers // 创建要插入的目标ViewController let customVC = CustomViewController() // 确定插入位置:比如在索引2的位置(也就是VC3的前面)插入 let insertIndex = 2 currentStack.insert(customVC, at: insertIndex) // 更新导航栈 navController.viewControllers = currentStack // 如果插入后想直接跳转到这个新VC,可以加上这句 navController.popToViewController(customVC, animated: true)
这样修改后,导航栈就变成了 VC1 -> VC2 -> CustomVC -> VC3,完全符合“在栈中间推入”的需求。
2. 点击通知时从App Delegate中以普通push方式跳转到任意ViewController
这里要分iOS版本来处理,iOS13之后苹果引入了SceneDelegate,所以我们需要兼容两种情况:
情况1:iOS13之前(仅使用AppDelegate)
在AppDelegate中,我们需要先找到当前活跃的导航控制器,再执行push操作。代码示例如下:
// 处理远程通知的方法 func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { handleNotificationJump() completionHandler(.newData) } // 处理本地通知的方法(如果需要) func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { handleNotificationJump() completionHandler() } // 核心跳转逻辑 private func handleNotificationJump() { guard let window = UIApplication.shared.keyWindow else { return } var currentNav: UINavigationController? // 判断根控制器是TabBar还是直接的NavigationController if let tabBar = window.rootViewController as? UITabBarController { currentNav = tabBar.selectedViewController as? UINavigationController } else if let nav = window.rootViewController as? UINavigationController { currentNav = nav } // 创建目标ViewController并push let targetVC = TargetViewController() currentNav?.pushViewController(targetVC, animated: true) }
情况2:iOS13及以上(兼容SceneDelegate)
iOS13之后,窗口属于具体的Scene,所以我们需要在SceneDelegate中处理跳转:
// SceneDelegate中处理远程通知 func scene(_ scene: UIScene, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) { handleNotificationJump(for: scene) } // 核心跳转逻辑 private func handleNotificationJump(for scene: UIScene) { guard let windowScene = scene as? UIWindowScene, let window = windowScene.windows.first else { return } var currentNav: UINavigationController? if let tabBar = window.rootViewController as? UITabBarController { currentNav = tabBar.selectedViewController as? UINavigationController } else if let nav = window.rootViewController as? UINavigationController { currentNav = nav } let targetVC = TargetViewController() currentNav?.pushViewController(targetVC, animated: true) }
要注意的是,如果你用了UNUserNotificationCenter,记得在AppDelegate或SceneDelegate的初始化方法中设置代理:UNUserNotificationCenter.current().delegate = self。
内容的提问来源于stack exchange,提问作者Hitesh Sharma
相关产品推荐
相关产品推荐

