dismissViewController实现多个模态视图跳转

来源:互联网 发布:汽车刷ecu软件 编辑:程序博客网 时间:2024/06/14 17:01

dismissViewControllerAnimated方法其原型为:

 - (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion;

1.flag的含义

         flag用于判断是否执行动画。completion是一个block,用于在dismiss之后执行回调。

presentViewController和dismissViewController是一组方法,用于展现和关闭模态视图,而且整个过程的动画是可以完全自定义的。

flag对自定义的动画的影响:flag == NO,那么不会执行任何动画(当然也不会执行自定义动画),如果flag == YES,则有可能执行自定义动画,如果没有自定义动画则会执行系统默认动画。

2.dismissViewController在哪里执行

        如果由A跳转到B,显然presentViewController方法应该在A里面执行,那么当我们希望关闭模态视图B时,在A视图控制器里执行

这是和pushViewController和popViewController那一组方法不同的地方。

不过在B视图中执行也是可以的,因为系统会自动优化,当B视图控制器没有present过其他视图控制器的时候,dismissViewController方法会自动交给B的presentingViewController执行,也就是A视图。

但是出于严谨性考虑,还是应该在A视图控制器中执行dismissViewController方法。

3.多个模态视图之间跳转

        若需要从视图C直接返回视图A。利用通知让B视图控制器执行dismissViewController方法,这样是不行的,因为对于一个视图控制器X,它执行dismissViewController方法的时候将会关闭它present的模态视图,只有在它没有present过模态视图的时候,才会交给他的presentingViewController执行dismissViewController方法。所以这里如果交给B执行,和直接在C里面执行dismissViewController方法的效果是一样的。显然一个最简单的解决办法就是利用通知或者代理,在A中执行dismissViewController方法。

        在present多个视图控制器的时候,系统维护了一个栈,以我们现在这个情况为例,从栈底到栈顶依次是A->B->C。当栈中某个位置的视图控制器执行dismissViewController方法的时候,栈中所有在它之上的视图控制器都会被dismiss,不同的是,栈顶的视图控制器将会以动画方式被dismiss,而中间的视图控制器只是简单的remove掉。这里已经成功了一半,因为dismissViewController总是要在A方法中执行的。不过这样做会遇到代码耦合的问题。(所谓的代码耦合指的是,我们应该尽量避免代理或者通知的使用,比如这时候A视图控制器换成了A’ 那么A’在不修改任何代码的时候肯定是无法直接放在整个项目里面使用的。此时要么重新实现协议,要么监听通知。

解决办法:

 UIViewController *rootVC =self.presentingViewController;

    while (rootVC.presentingViewController) {

        rootVC = rootVC.presentingViewController;

    }

    [rootVC dismissViewControllerAnimated:YEScompletion:nil];


在循环中连续获取presentingViewController,于是最终可以得到根视图控制器,这里就是A,不过这使得A视图控制器中不用添加任何代码,从而解决了耦合的问题。这样写的另一个好处是,不管是多少个视图控制器之间的跳转,都可以很方便的完成。



原创粉丝点击