iOS—push和present区别(含dismiss多级的方法)

  1. push和present都可以推出新的页面,present推出的是模态视图。
  2. present一般用于不同业务界面的切换,push一般用于同一业务不同界面之间的切换
  3. present与dismiss对应,push和pop对应。
  4. present只能逐级返回,push所有视图由视图栈控制,可以返回上一级,也可以返回到根视图、其他视图。

push方法

	NextViewController *next = [[NextViewController alloc] init];
    [self.navigationController pushViewController:next animated:YES];


pop的几种方法

	//返回上一级
	[self.navigationController popViewControllerAnimated:YES];

	//返回根视图
	[self.navigationController popToRootViewControllerAnimated:YES];

	//返回指定级数 (objectAtIndex:参数为想要返回的级数)
	[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:0]  animated:YES];


present方法

	SecondViewController *two = [[SecondViewController alloc] init];
 
    [self presentViewController:two animated:YES completion:nil];

dismiss方法

	//dismiss 只能逐级返回
	[self dismissViewControllerAnimated:NO completion:nil];

dismiss多级的方法

presentedViewController和presentingViewController是UIViewController里面的两个属性
PresentedViewController 与 PresentingViewController区别

  1. presentedViewController:The view controller that was presented by this view controller or its nearest ancestor.
    由这个视图控制器或它最近的祖先呈现的视图控制器
  2. presentingViewController:The view controller that presented this view controller (or its farthest ancestor.)
    呈现此视图控制器(或其最远祖先)的视图控制器。

假设从A控制器通过present的方式跳转到了B控制器,那么
A.presentedViewController 就是B控制器;
B.presentingViewController 就是A控制器;


举例:
四个视图A、B、C、D的跳转关系为A->B->C->D

当由D视图dismiss到A视图

    UIViewController *rootVC = self.presentingViewController;
     while  (rootVC. presentingViewController ) {
              rootVC = rootVC.presentingViewController ;
             }
    [rootVC dismissViewControllerAnimated:YES completion:nil];
    

当由D视图跳转到B视图(即dismiss两级)

    [self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
    

与第一种方法类似,通过判断dismiss到目标控制器

    UIViewController *rootVC =  self.presentingViewController;
    while (![rootVC isKindOfClass:[ViewController class]])  {
        rootVC = rootVC.presentingViewController;
    }
    [rootVC dismissViewControllerAnimated:YES completion:nil];
    

注意:

问题

以上方法中,一开始存在一些疑惑

 UIViewController *rootVC = self.presentingViewController;
     while  (rootVC. presentingViewController ) {
              rootVC = rootVC.presentingViewController ;
             }
    [rootVC dismissViewControllerAnimated:YES completion:nil];

这段代码执行完,dismiss返回到第一个视图。
代码中,循环结束,rootVC为第一个视图, 第一个视图执行dismiss方法后还是第一个视图????一般不都从第二个视图dismiss到第一个视图的吗

解答

这里就要提到dismissViewController到底在哪里执行

如果由A跳转到B,显然presentViewController方法应该在A里面执行。而 dismissViewController也是在A视图控制器里执行

苹果文档里的一段话:
The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, it automatically forwards the message to the presenting view controller.
翻译如下:
呈现视图控制器负责解散它呈现的视图控制器。如果你在被呈现的视图控制器本身上调用这个方法,它会自动将消息转发给呈现的视图控制器。

即在B中调用dismiss方法,dismiss方法会自动交给B的presentingViewController即A视图里执行。

	//在B中
    //返回上一级  两种写法效果一样
    [self dismissViewControllerAnimated:NO completion:nil];
    
    //[self.presentingViewController dismissViewControllerAnimated:NO completion:nil];
    

如果A->B->C->D, 由D dismiss 到 A;

这里对于在A中执行dismiss从而实现多级跳转到A的解释如下:

苹果文档里的解释
If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.
翻译如下:
如果你连续呈现几个视图控制器,从而建立一个被呈现的视图控制器的堆栈,在堆栈中较低的视图控制器上调用这个方法会解散它的直接子视图控制器和堆栈上那个子视图控制器上面的所有视图控制器。当这种情况发生时,只有最顶端的视图以动画的方式消失;任何中间视图控制器都可以从堆栈中删除。最顶层的视图使用它的模态转换样式被驳回,这可能与堆栈中较低的其他视图控制器使用的样式不同。

即present多个视图控制器的时候,系统维护了一个栈,
栈底到栈顶依次是A->B->C->D,当在A中执行dismiss方法,栈中在A之上的视图都会被dismiss。不同的是,栈顶的视图控制器将会以动画方式被dismiss,而中间的视图控制器只是简单的remove掉。

最后,需要注意的是,使用代理或通知的话,代码的耦合度会比较高,实现和修改起来都很麻烦。所以实现多级dismiss还是建议使用上面介绍的方法哈哈哈哈哈


github地址

参考文章:https://blog.csdn.net/sinat_30898863/article/details/50950915

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值