【iOS】present和push
present和push的比较
-
present和push都用于iOS的视图切换,并且切换都是可逆的,原始视图不会被销毁,还可以直接更改window的rootViewController来切换视图,但是这种方法不可逆,并且原始视图会被销毁
-
present一般用于不同业务界面的切换,push一般用于同一业务不同界面的切换
-
present和dismiss对应,push和pop对应
-
present只能逐级返回,push有栈控制,但是可以返回任意级 ?
push方法
SecondViewController* secondViewController = [[SecondViewController alloc] init];
[self.navigationController pushViewController:secondViewController animated:YES];
pop方法
//返回上一级视图
[self.navigationController popViewControllerAnimated:YES];
//返回根视图
[self.navigationController popToRootViewControllerAnimated:YES];
//返回指定级数
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:0]];
这里返回到指定级数的方法,是通过访问视图控制器属性来获得视图控制器数组,在这个数组中可以获得导航控制器的每一层视图,再调用popToViewController方法就可以回到指定级数的视图。
present方法
SecondViewController* secondViewController = [[SecondViewController alloc] init];
[self presentViewController:secondViewController animated:YES completion:nil];
dismiss方法
[self dismissViewControllerAnimated:NO completion:nil];
dismiss多级的方法
两个属性
在讲解dismiss多级视图控制器的方法之前,先来了解一下presentedViewController和presentingViewController这两个UIViewController的属性。
举个例子:如果B控制器是由A控制器present弹出的,那么:
A.presentedViewController = B;
B.presentingViewController = A;
dismiss多级
现在来实现A、B、C、D四个视图控制器通过dismiss来实现多级之间的跳转。假设A、B、C、D四个视图之间的跳转关系为A->B->C->D
由D视图dismiss到A视图
UIViewController *rootViewController = self.presentingViewController;
while (rootViewController.presentingViewController) {
rootViewController = rootViewController.presentingViewController;
}
[rootViewController dismissViewControllerAnimated:YES completion:nil];
dismiss两级
[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES];
也可以向前遍历来访问要dismiss的视图
UIViewController *ViewController = self.presentingViewController;
while (![ViewController isKindOfClass:[SecondViewController class]]) {
ViewController = ViewController.presentingViewController;
}
[ViewController dismissViewControllerAnimated:YES completion:nil];
注意
这里的dismiss与我们以前常用的dismiss用法不同,以前都是被切换出的视图控制器调用dismiss方法来回到上一级视图控制器。而这里却是要回到哪一级视图控制器,就哪一级视图控制器调用dismiss方法。
那么dismissViewController到底在哪里执行呢?
其实,如果由A跳转到B,presentViewController方法在A里面执行,而dismissViewController也是A视图控制器来调用
什么意思呢?
其实就是如果在B中调用dismiss方法,dismiss方法会自动交给B的presentingViewController(也就是AViewController)来执行。
//在B中返回上一级
[self dismissViewControllerAnimated:NO completion:nil];
[self.presentingViewController dismissViewControllerAnimated:NO completion:nil];
//这两种写法效果一致
对于在A中执行dismiss从而实现多级跳转到A的解释如下:
也就是说,当present多个视图控制器时,系统维护了一个栈,栈中存放着A、B、C、D四个视图控制器。当在A中执行dismiss方法,栈中在A之上的视图就会被dismiss掉,不同的是,栈顶视图会以动画形式dismiss,而中间的视图控制器只是简单地remove掉。