如何将Navigation Controller栈中指定ViewController前置且不移除顶部页面
导航控制器栈指定ViewController置顶实现方案
可以实现该需求,核心操作是直接修改UINavigationController的viewControllers栈数组顺序,无需销毁栈中任意页面,也不需要重新加载目标ViewController。
实现原理
UINavigationController的viewControllers属性支持直接赋值修改,栈的展示顺序完全和数组顺序一致:数组最后一位为当前最上层展示的页面。我们只需要将目标ViewController从原有位置取出,插入到数组最后一位,再重新给导航控制器赋值新的栈数组即可。
该操作不会触发目标ViewController的viewDidLoad方法,仅会触发页面展示相关的生命周期回调,符合不重新加载的要求;原有栈顶部的所有页面都不会被销毁,仅调整顺序到目标ViewController下方,后续pop操作仍然可以正常回到这些页面。
代码示例
Swift 代码
// 获取当前导航栈数组 var navStack = navigationController?.viewControllers ?? [] // 匹配查找目标ViewController,可自行修改匹配规则 guard let targetIndex = navStack.firstIndex(where: { $0 is YourTargetViewController }) else { // 栈中未找到目标ViewController的逻辑自行处理 return } // 调整栈顺序 let targetVC = navStack.remove(at: targetIndex) navStack.append(targetVC) // 赋值新栈,animated参数控制是否展示转场动画 navigationController?.setViewControllers(navStack, animated: true)
Objective-C 代码
// 获取当前导航栈数组 NSMutableArray *navStack = [self.navigationController.viewControllers mutableCopy]; NSInteger targetIndex = NSNotFound; // 匹配查找目标ViewController,可自行修改匹配规则 for (NSInteger i = 0; i < navStack.count; i++) { if ([navStack[i] isKindOfClass:[YourTargetViewController class]]) { targetIndex = i; break; } } if (targetIndex == NSNotFound) { // 栈中未找到目标ViewController的逻辑自行处理 return; } // 调整栈顺序 UIViewController *targetVC = navStack[targetIndex]; [navStack removeObjectAtIndex:targetIndex]; [navStack addObject:targetVC]; // 赋值新栈,animated参数控制是否展示转场动画 [self.navigationController setViewControllers:navStack animated:YES];
注意事项
- 如果不需要转场动画效果,将
animated参数改为false(Swift)或NO(Objective-C)即可,页面会直接切换到目标ViewController - 可根据业务需求修改匹配目标ViewController的规则,不局限于按类匹配,也可通过唯一标识属性等方式匹配
内容的提问来源于stack exchange,提问作者Ginso
相关产品推荐
相关产品推荐

