• 模态跳转


    需求:A视图控制器中presentB视图控制器,B视图控制器再presentC视图控制器。最后从C视图控制器直接返回到A视图控制器。
     
    1、一些解释
    1.1两个常用的方法 
    /** 
    * 展示模态视图 
    * 
    * @param viewControllerToPresent 调转的目标控制器 
    * @param flag 如果flag == NO,那么不会执行任何动画(当然也不会执行自定义动画);如果flag == YES,则有可能执行自定义动画,如果没有自定义动画则会执行系统默认动画。 
    * @param completion 跳转完成后的回调 
    */ 
    - (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion;
    /** 
    * 关闭模态视图 
    * 
    * @param flag 如果flag == NO,那么不会执行任何动画(当然也不会执行自定义动画);如果flag == YES,则有可能执行自定义动画,如果没有自定义动画则会执行系统默认动画。 
    * @param completion 关闭完成后的回调 
    */
     - (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion;

    1.2两个名词说明

    @property(nullable, nonatomic, readonly) UIViewController *presentedViewController  NS_AVAILABLE_IOS(5_0);
    
    @property(nullable, nonatomic, readonly) UIViewController *presentingViewController NS_AVAILABLE_IOS(5_0);

    A present B,A.presentedViewController是B,B.presentingViewController是A。
     
    2、dismissViewController在哪里执行?
    我们最常使用的一种场景:A视图控制器present跳转到B视图控制器,B视图控制器dismiss回到A视图控制器,所以会想当然的以为dismissViewController这个方法是在B视图控制器里面执行。
     
    标准答案是:在A视图控制器里执行。
     
    但是,在上述场景中,用B视图控制器执行也是可以的,因为系统会自动优化,当B视图控制器没有present过其他视图控制器的时候,dismissViewController方法会自动交给B视图控制器的presentingViewController执行,也就是A视图控制器。
     
    3、多个模态视图之间跳转
    在网上也看到一些解答,比如说利用通知让B视图控制器执行dismissViewController方法。其实这样是不行的,原因刚刚已经解释过,对于一个视图控制器X,它执行dismissViewController方法的时候将会关闭它present的模态视图,只有在它没有present过模态视图的时候(但是这里B已经present到C了),才会交给他的presentingViewController执行dismissViewController方法。所以这里如果交给B执行,和直接在C里面执行dismissViewController方法的效果是一样的。
    显然一个最简单的解决办法就是利用通知或者代理,在A中执行dismissViewController方法。此时B和C视图控制器会发生什么变化呢?
    依然摘录一段苹果的文档做一下解释:
    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。当栈中某个位置的视图控制器执行dismissViewController方法的时候,栈中所有在它之上的视图控制器都会被dismiss,不同的是,栈顶的视图控制器将会以动画方式被dismiss,而中间的视图控制器只是简单的remove掉。
    这种方法是可行的,因为 dismissViewController总是要在A方法中执行的。不过这样做会遇到代码耦合的问题。 
     
    一种低耦合的解决方案:
    // C视图控制器触发dismiss方法前添加这么一段代码 
    UIViewController *rootVC = self.presentingViewController; 
    // rootVC.view.alpha = 0; 
    while (rootVC.presentingViewController) { 
    rootVC = rootVC.presentingViewController; 
    } 
    [rootVC dismissViewControllerAnimated:YES completion:nil];

    在循环中连续获取presentingViewController,于是最终可以得到根视图控制器,这里就是A,不过这使得A视图控制器中不用添加任何代码,从而解决了耦合的问题。
    这样写的另一个好处是,不管是多少个视图控制器之间的跳转,都可以很方便的完成。
    缺点:你会明显的感觉到是从C->B->A,有没有一种完美的解决方案,让用户感觉直接从C->A?
    这句代码rootVC.view.alpha = 0;的加入可以让达到C->A的效果,但是Animated的设置就无效了。
    还是最完美的解决方法。 
     
    4、注意,模态跳转的方法已经变更,新的跳转方法,必须进行相关设置
    RevokeApplyViewController *revokeApplyVC = [[RevokeApplyViewController alloc] init];
    revokeApplyVC.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    revokeApplyVC.modalPresentationStyle = UIModalPresentationOverCurrentContext;
    revokeApplyVC.view.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.4];
    [self presentViewController:revokeApplyVC animated:NO completion:nil];
  • 相关阅读:
    Mysql大量插入随机数据方法--存储过程
    Linux永久修改系统时间和时区方法
    python反转字符串(简单方法)及简单的文件操作示例
    sql怎么批量替换字段里的字符串的
    varchar和Nvarchar区别
    VS改大小写的快捷键
    SQL中PIVOT 行列转换
    [转]VS中展开和折叠代码
    Bootstrap 标签页(Tab)插件
    C# DataTable 和List之间相互转换的方法
  • 原文地址:https://www.cnblogs.com/cchHers/p/8711998.html
Copyright © 2020-2023  润新知