美文网首页iOS DeveloperiOS 开发
关于setNavigationBarHidden引起的导航栏异常

关于setNavigationBarHidden引起的导航栏异常

作者: 忧郁的小码仔 | 来源:发表于2016-08-11 09:11 被阅读3552次

最近项目中遇到一个很奇怪的问题,项目的主控制器导航栏需要隐藏,从主控制器Push出来的控制器中的导航栏都要显示。

结果有一天,闲来无事,从主控制器Push出来一个控制器之后,就把push出来的控制器往右滑(导航控制器关闭一个控制器的手势),然后在这个Push出来的控制器快消失的时候,又把它复原,结果,再Push控制器的时候,导航栏的标题和返回按钮全都乱了。如下图

执行结果.gif

测试工程

后来在Stack Overflow上看到了一个很不错的解决方法:

首先,导航控制器的pop手势操作其实也是一种动画,当用手势操作导航控制器pop的时候,其实我们看到的是动画执行的过程而已,只是动画和我们的手势同步而已。当pop手势取消的时候,系统会决定该动画是rollBack还是一直执行到end。

接下来,就是上面现象产生的原因了

1.这是解决方法一:注意到测试工程里面隐藏导航栏是写在viewWillAppear里面的,问题就在这里。

-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES];
}

当pop手势执行的时候,第一个控制器的viewWillAppear就开始执行了。根据苹果的解释,"view will appear" actually means "view might appear". 意思已经很明显了,我们更应该把隐藏导航栏的代码放到viewDidApear里面去,因为只有pop手势结束的时候才会执行viewDidApear.

2.解决方法二:导航栏标题和返回按钮变乱的根本原因是什么呢?

这里隐藏着第二种动画,所有和导航栏相关的(比如title, 比如返回按钮)。运行时会自己来决定这个动画该怎么执行。但是测试工程中我是没有使用动画的。所以,我们应该使用动画而不是取消动画导致最终效果不协调。

[self.navigationController setNavigationBarHidden:YES animated:YES];

3.解决方法三: 但是,有时候上面两种解决方法并不是正确的解决姿势,比如我的项目中就不太适合第一种解决方式。所以,最终的解决方法来了:

系统专门提供了一个动画过渡协调类来解决这个问题_,我们可以使用这个类来处理上面动画取消或完成时的动作。(把第一个控制器的viewWillAppear改写如下即可了)

-(void)viewWillAppear:(BOOL)animated{
    [superview WillAppear:animated];
    id<UIViewControllerTransitionCoordinator> tc =self.transitionCoordinator;
    if(tc && [tc initiallyInteractive]) {
        [tc notifyWhenInteractionEndsUsingBlock:
         ^(id<UIViewControllerTransitionCoordinatorContext> context) {
             if([context isCancelled]) {
                 // do nothing!
             }else{// not cancelled, do it
                 [self.navigationController setNavigationBarHidden:YESanimated:NO];
             }
         }];
    }else{// not interactive, do it
        [self.navigationController setNavigationBarHidden:YESanimated:NO];
    }
}

感谢万能的Stack Overflow.

相关文章

网友评论

    本文标题:关于setNavigationBarHidden引起的导航栏异常

    本文链接:https://www.haomeiwen.com/subject/jrsjsttx.html