相信大家对navigationController
的跳转都不陌生,还记得微信里面联系人详细资料里面的发消息按钮点击后的效果和切换语言后的效果吗,UINavigationController是实现画面多层次跳转,并且可以自动地记忆跳转所经过的路径,按照这些记录的路径信息,可以依次返回到上层画面中.
基本跳转:
在使用UINavigationController
时我们用的最多的就是Push
和pop
方法,而pop
方法又包括popViewControllerAnimated
、popToViewController
与popToRootViewControllerAnimated
,分别是返回上一层,返回指定层与返回根视图(即UINavigationController
最开始的那一层)
我们在运用这些跳转时,每push
一层都会将一个页面保存到self.navigationController.viewControllers
里,相应的pop就是将页面从self.navigationController.viewControllers
移除的过程.
实现一个需求:pop
掉当前的界面同时push
出一个新的界面:
过程分析:
开始做法很简单,在返回时pop
掉B页面即可
self .navigationController.popViewControllerAnimated(false )
然后push
新页面C
self .navigationController.pushViewController(C , animated: true )
这种看似合理的方法其实也有问题,就是即使pop
时关闭了动画,A页面依然会闪现一下,于是想到了新的思路,对self.navigationController.viewControllers
进行操作,因为viewControllers: [UIViewController]
,就是一个数组.将这个数组取出对他进行操作,再赋值
var controllerArr = self.navigationController ?.viewControllers
controllerArr?.insert (C, atIndex:controllerArr?.count -2 )
self.navigationController ?.viewControllers = controllerArr
self.navigationController ?.popViewControllerAnimated (true)
效果完成了需求中的效果,但是发现B页面依然在self.navigationController?.viewControllers
中储存的Controller
中,导致数据在传输时数据会出现影响.后来当看到setViewControllers
这个方法时,突然觉得刚才那个就是个错.
public func setViewControllers(viewControllers: [UIViewController], animated: Bool)
// If animated is YES, then simulate a push or pop depending on whether the new top view controller was previously in the stack.
即从iPhone OS 3.0
以后,可以通过调用setViewController
方法将画面的跳转历史路径(堆栈)完全替换,(这个才是正解)
B页面返回时跳转新页面C
var controllerArr = self.navigationController ?.viewControllers //获取Controller数组
controllerArr?.removeAll ()//移除controllerArr中保存的历史路径
//重新添加新的路径
controllerArr?.append (self.navigationController ?.viewControllers [0 ])
controllerArr?.append (C)
//将组建好的新的跳转路径 set 进self.navigationController 里
self.navigationController ?.setViewControllers (controllerArr!, animated: true)//这里直接setViewControllers即可,不需要push 或者pop 方法
A页面跳转到B页面时,添加新页面C
即在B页面加到navigationController
里之前修改页面路径
var controllerArr = self.navigationController ?.viewControllers //获取Controller数组
controllerArr?.removeAll ()//移除controllerArr中保存的历史路径
//重新添加新的路径
controllerArr?.append (self.navigationController ?.viewControllers [0 ])
controllerArr?.append (C)
controllerArr?.append (B)
//这时历史路径为(root -> c -> b)
//将组建好的新的跳转路径 set 进self.navigationController 里
self.navigationController ?.setViewControllers (controllerArr!, animated: true)//直接写入,完成跳转B页面的同时修改了之前的跳转路径
然后在B页面里就可以直接返回pop
上一层,就是想要的C页面.