之前写过一篇文章解决navigationbar的渐变等自定义相关问题。今天写这个文章是想写一下这两天自己遇到的关于navigationbar的一些比较难解决的问题。navigationbar真的是一个宝藏,啥时候都能有新收获。
原理
每一个被push进来的页面都有自己的navigationcontroller,通过navigationcontroller可以取到。关于这一点我们可以在代码里看到。
如果连续push3个页面,那么这三个页面的navigationcontroller都是同一个。这一点我们通过打印三个页面的self.navigationcontroller的地址就可以知道。
也就是说navigationcontroller像是一个房间,每个viewcontroller像是一个人,一个房间可以住进很多个人,每个人都可以找到自己的房子,住进这个房间以后就可以改变房子的外观等属性,就像是我们可以装修刷漆等等。
常见问题
了解了这一点以后,很多关于导航栏的bug的原因自然也就了解。
- 设置了隐藏导航栏但是没有隐藏
首先要看设置导航栏是否在viewWillAppear,如果是,那么执行完这个方法,而前一个VC还没有销毁的时候,如果执行了viewDidDisappear中的显示导航栏方法,就无法隐藏了。如果检查了发现没有问题,就要看是不是设置了当前页面的navigationcontroller的导航栏隐藏,这个问题比较容易出现层级中有present的页面或者tabcontroller的情况下。如果都不是,bug的效果是闪现一下导航栏,最终没有显示的情况,就要看前一个页面是否设置了显示,而且前一个页面在当前页面被推出之前并没有执行到viewWillAppear方法而是之后才执行的。这种情况下可以通过延迟二级页面的push解决。 - 通过右滑手势返回上一页的时候,滑动产生偏移立即松手,会出现当前导航栏消失的情况。
如果前一页隐藏了导航栏,而当前页设置了显示导航栏,就可能会出现这样的情况,比较少见,但是确实存在。当时遇到这个bug的时候很懵逼,因为网上能查到的资料也不多。最终在GitHub上找到了解决方案。
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
//MARK:偶尔在非常快速的从第二个页面取消拖返的时候,这里的输出会是 1 0 1 0。但是第二次的set hidden to no是有效的。
//猜测可能是由于动画animated的原因,造成了第一次set hidden to no的还原。具体未知
//所以我们在下一个runloop里去重新设置下应该就OK了
// DLOG(@"1.hidden:%d",self.navigationController.navigationBarHidden);
if (self.navigationController.navigationBarHidden) {
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
// DLOG(@"2.hidden:%d",self.navigationController.navigationBarHidden);
dispatch_async(dispatch_get_main_queue(), ^{
// DLOG(@"3.hidden:%d",self.navigationController.navigationBarHidden);
if (self.navigationController.navigationBarHidden) {
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
// DLOG(@"4.hidden:%d",self.navigationController.navigationBarHidden);
});
}
但是建议大家不要直接使用这个方法,最好是在出错页面的viewDidAppear方法中去修改,这样不会影响到其他页面。
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.navigationController setNavigationBarHidden:NO animated:NO];
if (self.navigationController.navigationBarHidden) {
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
dispatch_async(dispatch_get_main_queue(), ^{
if (self.navigationController.navigationBarHidden) {
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
});
}
遇到的比较难解决的问题暂时就是这两个,其他问题诸如手势返回的时候导航栏消失,都是因为没有设置动画等比较简单的原因,也比较容易在网上找到答案,在这里就不再赘述了。
大家有遇到其他问题或者对文中有什么觉得不对的地方可以发在回复里,我们一起探讨啊。