1.遇到一个需求
使用UINavigationController
push进入多个页面后,不再显示部分页面,直接返回到指定的页面。
根据描述,第一个想到的方案就是:
1
[self.navigationController popToViewController:toVC animated:YES];
通过遍历UINavigationController
的viewControllers
找到要跳转的页面,直接pop过去。
遇到的问题就是,iOS 触发返回页面有两种交互方式:
- 点击左上角的返回按钮
- 使用手势,在屏幕边缘从左往右滑动
要想使用pop
的API,就需要拦截边缘滑动的交互事件,重写UINavigationController
的手势,(有的朋友说可以屏蔽右滑手势…)
由于不想改动 UINavigationController
的手势事件,遂有了下一个方案。
2.UINavigationController
实现原理
在iOS开发过程中,UINavigationController
是常用的容器类Controller,UINavigationController
交互方式如下图,
根据官方文档说明,UINavigationController
通过管理一个用数组实现的栈结构来管理childControllers
。 将UIViewController
依次压入栈中,记录了页面的先后顺序,同时栈持有子视图,实现了内存的管理。
3.解决方案
于是想到,通过修改UINavigationController
栈内元素来控制页面的跳转。
1
2
3
4
5
6
NSMutableArray *vcStack = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
if (vcStack.count > 2 && vcStack.count > index) {
//将 元素直接从 数组中 移除
[vcStack removeObjectAtIndex:index];
self.navigationController.viewControllers = vcStack;
}
这样,在进入新的页面时,将不再显示的页面从栈中移除掉,便可实现跨页面的跳转。
需要注意的是:
- 当把一个
UIViewController
的实例push进栈后,该实例的parentViewController
就是UINavigationController
- 调用
UIViewController
的- (void)removeFromParentViewController
方法,会将该实例从栈中移除,但会发生异常,具体表现为点击返回,navigationBar
有动画,但不会有页面跳转 - 注意内存的引用,如果要移除的
UIViewController
在其他地方存在引用,将不会释放内存,发生内存泄露。
附:UI结构图
参考资料:
UINavigationController