参考自 ZYWu 的 《iOS ViewController跳转界面的几种方法简单总结》,时光追寻的《iOS 浅谈页面跳转与返回的几种方法》.
1.导航控制器 UINavigationController push一个新页面
navigationController 是 UIViewController的属性,这个属性 UIViewController通过扩展了UINavigationControllerItem得到的,而不是 UIViewController直接存在的属性。
push新页面,用pushViewController: animated:;返回上一页面用popViewControllerAnimated:;返回根视图,即栈顶,用popToRootViewControllerAnimated:;返回某一页面,用popToViewController: animated:,这里要求只能返回栈内的页面,即self.navigationController.viewControllers数组中的页面;其中,如果新页面的导航,返回按钮等用的是系统的,则不需要设置返回响应。
这里有一个问题,要想使用push方式,必须self.navigationController不为nil才可以,即上一页面push的当前页面或者当前页面是UINavigationController的RootViewController.
工作原理:
通过栈的方式实现,遵循先进后出原则。push就是将对象压入栈中,pop则是将对象移除栈。viewControllers就是实现栈效果的数组,压入栈中的对象都在数组中。
动画效果:
默认动画效果是从右往左缓慢推出,默认无动画效果是从右往左快速推出,一闪而过。
2.模态跳转
推出新页面用presentViewController: animated: completion:;返回用dismissViewControllerAnimated: completion:;是UIViewController的方法,直接使用。
其中UIImagePickerController从系统相册选取照片或者拍照,imagePickerController和弹出它的VC之间就通过UIImagePickerControllerDelegate实现交互的,用的就是模态跳转。
控制器有两个和模态跳转有关的很有用的属性,是presentedViewController和presentingViewController。从应用的语法时态大致能猜测到一个是已推出的控制器,一个是正在推的控制器。举个例子,比如说, 控制器A和B,[A presentViewController B animated:YES completion:nil]; 那么A相对于B就是presentingViewController,B相对于A是presentedViewController,即B.presentingViewController = A,A.presentedViewController = B。这个个人感觉主要是用于层层模态推出的控制器,在最后一层却要一次返回到第一个控制器的情况。实现方法通过这个属性,层层遍历找到最上层的控制器,执行返回操作:
UIViewController *vc = self.presentingViewController;
while (vc.presentingViewController) {
vc = vc.presentingViewController;
}
[vc dismissViewControllerAnimated:YES completion:NULL];
一般情况可以通过效果来区分是 模态还是push,其中模态推出默认效果是新控制器从屏幕的最底部往上钻,直到盖住之前的控制器为止。但可以通过自定义转场来改变展现view的动画,大小,位置,是否移除跳转之前的view.这个效果可以用来模拟ipad特有的Popover弹出框。
动画效果:
模态推出不设置动画效果时是闪一下完全展示出来,返回是闪一下消失。设置有动画效果,默认效果是从底部往上钻出来,返回的默认效果是从上往下消失。
设置动画效果的属性是modalTransitionStyle,现在有四种效果分别是,UIModalTransitionStyleCoverVertical 从底部滑入,UIModalTransitionStyleFlipHorizontal,水平翻转进入,UIModalTransitionStyleCrossDissolve,交叉溶解和UIModalTransitionStylePartialCurl,翻页。 其中,感觉UIModalTransitionStyleCrossDissolve,交叉溶解效果和无动画效果差不多,其余三种动画效果都很明显。
其中,如果想有动画效果,那么 设置动画效果的Bool值要置为YES,然后推出新页面的时候,设置新页面的modalTransitionStyle,即newVC.modalTransitionStyle,推出的时候就有动画效果了。如果你设置了动画效果的Bool值为NO,那么无论你怎么设置modalTransitionStyle都不会有动画。如果你设置了当前页面的modalTransitionStyle,那么推出新页面的动画效果也不会是你设置的效果。返回的时候,要分别设置动画效果Bool值和返回页面的modalTransitionStyle,即self.modalTransitionStyle.
3.通过segue来跳转
此方法仅适用于Storyboard中各个页面连线后的跳转,鼠标点击viewControlller,按住control键拖拽到另一个View页面,在弹出的segue页面中选择跳转模式即可,连线完之后选中连线,在Identifier填上对应的标示,然后再在需要跳转的地方实现如下代码即可:
[self performSegueWithIdentifier:@"test" sender:self];
如果连线的方式是push,则ViewController需要由UINavigationController来管理,返回方式则和UINavigationController一样
如果连线的方式是model,则ViewController不需要由UINavigationController来管理,返回方式和模态的返回方式一样
如果连线的方式是custom,则需要自定义segue,自定义segue在此不讨论。
4.UITabBarController
tabbar控制器,同样是常用的界面切换方式,一般作为app的根界面的视图控制器。实现的效果其实是持有的页面的切换,而不是跳转。
普通情况,UITabBarController + push就构成了APP的切换架构了。
今天解决一个BUG时用到了这一块的知识,特此做个记录。在APP中,push和模态跳转在同一业务线上最好不要混用。一旦混用,会造成推进返回的中断。
若对文章所述内容有不明白的,欢迎随时提问,定期解答。对文章所讲内容有遗漏或者错误的,欢迎斧正。