导航栏隐藏 && 导航栏错乱

作者: 李国安 | 来源:发表于2016-08-23 15:56 被阅读3508次

有感

....请允许我在文章开篇爆句粗口, 就这导航栏错乱这 Bug, 我真日了狗了. 自从测试小伙伴发现这个问题以来, 已经有几天的时间了, 就复现这个 Bug, 就花费了大笔时间. 调研了半天才终于把这个 Bug 复现了. 写这篇文章的目的, 一个是记录一下项目中遇到的疑难杂症, 另一个就是希望能帮助到那些同样被这些问题困扰的小伙伴们. 总之, 这一段就是吐槽一下. 废了那么多话, 开始正题吧. 先放出来一个 Demo.

Demo

先给大家 Demo 的下载地址 Click Here
简单的讲解一下这个 Demo:

  1. KeyWindowRootViewController 是一个UITabBarViewController
  2. UITabBarViewController 的每一个ViewController 都嵌套了一个MLNavigationController.
  3. 每一个ViewController 都继承自MLBaseViewController.
  4. MLBaseViewController.h 中, 声明了一个枚举类型MLNavigationHiddenType, 这个枚举类型来控制整个工程隐藏NavigationBar 的方式.
  5. MLBaseViewController.h 中还声明了一个全局变量hiddenType, 用这个变量来设置整个工程隐藏NavigationBar 的方式.
  6. 整个工程中, 只有MLUserHomePageViewController, MLMineViewControllerMLLoginViewControllerNavigationBar 处于隐藏状态.

OK, 差不多介绍到这里吧, 细节部分大家具体看代码吧.

Demo 中使用的隐藏方式

  1. [self.navigationController setNavigationBarHidden: YES];
  2. [self.navigationController setNavigationBarHidden: YES animated: NO];
  3. [self.navigationController setNavigationBarHidden: YES animated: YES];
  4. [self.navigationController setNavigationBarHidden: YES animated: animated];
  5. self.navigationController.delegate = self 这种方法在最后为大家讲解, 这其实才是真正的究极方法

其实NavigationBar的显示与隐藏其实很简单, 只需要在ViewControllerviewWillAppear 中隐藏 NavigationBar, 在试图控制器的 viewWillDisappear 中显示 NavigationBar就可以了, 但是仅仅这么做, 会带来一些 UI 上的 Bug, 其实我们也可以定义一些成员变量来控制 Bug 的产生, 但是很繁琐, 项目庞大了之后, 会导致代码极其不易维护。代码如下:

- (void) viewWillAppear:(BOOL)animated {
  [super viewWillAppear: animated];

  // 方法1
  [self.navigationController setNavigationBarHidden: YES];

  // 方法2
  [self.navigationController setNavigationBarHidden: YES animated: NO];

  // 方法3
  [self.navigationController setNavigationBarHidden: YES animated: YES];

  // 方法4
  [self.navigationController setNavigationBarHidden: YES animated: animated];
}

- (void) viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear: animated];

  // 方法1
  [self.navigationController setNavigationBarHidden: NO];

  // 方法2
  [self.navigationController setNavigationBarHidden: NO animated: NO];

  // 方法3
  [self.navigationController setNavigationBarHidden: NO animated: YES];

  // 方法4
  [self.navigationController setNavigationBarHidden: NO animated: animated];
}

文中将会涉及到的 Bug

__Bug__1: 没有导航栏的试图控制器没有导航栏的试图控制器之间的切换效果.
__Bug__2: 没有导航栏的控制器有导航栏的控制器 之间进行切换的效果.
__Bug__3: 没有导航栏的控制器 Present 一个 视图控制器 的效果.
__Bug__4: NavigationBar 错乱.
__Bug__5: UITabBarController 切换ViewController 的效果.

几种隐藏导航栏方法产生的问题

方法1 [self.navigationController setNavigationBarHidden: YES];

方法2 [self.navigationController setNavigationBarHidden: YES animated: NO];

先来说说方法1方法2, 其实这两个方法效果是几乎一样的, 全都是隐藏NavigaionBar并且不需要使用动画. 我们先来看一下效果, 下面这张动图是 没有导航栏的控制器没有导航栏的控制器 之间进行切换的效果:

没有NavigationBar 的两个 ViewController 切换效果

其实这个效果还算可以, 也没有什么非常不友好的 UI 效果, 但是接下来的动图, 就会给用户带来一些很不愉快的体验: Bug2没有导航栏的控制器有导航栏的控制器 之间进行切换的效果:

没有NavigationBar 和 有NavigationBar 的 ViewController 切换效果
可以清楚的看到, 在使用Pop 返回手势的时候, 右上角有一个非常明显的黑色区域, 效果非常不尽如人意, 其实不友好的地方不仅仅只有这一个地方, 看下图: Bug3 没有导航栏的控制器 Present 一个 视图控制器 的效果: 没有NavigationBar 的 ViewController Present 一个 ViewController
由于我们在 viewWillDisappear 方法中, 做了显示NavigationBar 的操作, 所以当我们点击登录按钮的一瞬间, 导航栏出现了. 这会给细心的用户带来一种非常匪夷所思的感觉, 同样非常的不友好. 但是如果仅仅如此的话, 可能有些小伙伴也就忍了, 也就懒得继续钻研下去了, 但是... 重点来了, 使用方法1方法2隐藏NavigationBar, 会带来一个非常不可思议的 Bug, 也就是本文题目中写道的, NavigationBar错乱的 Bug, Bug4 请仔细看下面这个动图(这个动图时间有点长, 所以质量下降了, 主要观察NavigationBar部分就可以了): NavigationBar 错乱 Bug

我相信一定不止是我一个人遇到了这个问题, 在网上搜索了很多帖子, 确实也有不少的小伙伴遇到了这个问题, 我先来说一下这个问题的复现方法:

  1. 需要3个ViewController (至少3个, 更多也可以), 隐藏第一个ViewControllerNavigationBar(其实你隐藏哪个都可以, 我这里以第一个为例)
  2. push 进入ViewController2, 使用 iOS7后系统的右划返回手势, 这里注意一下, 手指右划到一半的时候, 取消Pop 动作, 此时页面依然停留在ViewController2当中, 然后再完整的做一次右划手势PopViewController1.
  3. 这个时候, 实际上这个NavigationContrllerNavigationBar 结构已经错乱了, 我们可以PushViewController3中去看一下NavigationBar 的情况. (无论是 PushViewContrller3 或者是 PushViewController4,ViewController5,ViewController6, 你会发现所有的ViewContrllerNavigationBar 都会非常神奇的一闪而过, 然后变成了 ViewController2NavigationBar)

我只想说: WTF, 好神奇的样子. 其实这个 Bug 复现起来并不是很困难, 难点在于:
你的测试小伙伴会给你提 Bug 说:

ViewController3的导航栏有问题, 但是这个问题非常偶然, 我也没有办法复现.

WTF, 你不复现我怎么办, 难道真的要我把需求放下, 来花大笔的时间来复现这个 Bug 么? T_T...
不过还好, 这个 Bug 我这边已经帮助大家复现出来了, 我相信, 一定会帮助到一些已经在风中凌乱了的小伙伴们( OK, 装逼结束, 其实是在 Google 上搜索到了这个小伙伴的文章后受到了启发, 不过这篇文章中, 并没有给出一个非常 Prefect 的解决办法).
好了, 废话不多说了, 接下来看看到底该怎么解决上面这个 Bug , 以及上面提到的 UI 不友好的地方吧, 接下来, 我们来看方法3.

方法3 [self.navigationController setNavigationBarHidden: YES animated: YES];

使用方法3来设置NavigationBar 的隐藏和出现, 经过测试, 解决了 Bug2 没有导航栏的控制器有导航栏的控制器 之间进行切换的效果, 看下图:

解决的 Bug
方法3确实解决了 Bug2, 其实方法3也同样的解决了NavigationBar 错乱的问题, 经测试, 隐藏NavigaionBar 的时候, 将动画属性置为YES, 就能解决NavigationBar 错乱的问题了, 但是这样做也是会付出一些代价的.
  • 首先: Bug3 没有导航栏的控制器 Present 一个 视图控制器 的效果, 并没有得到解决. (大家可以自行查看 Demo)
  • 其次: 将动画属性设置为 YES 之后, 会带来两个新的问题, 我将这两个问题定义为 Bug1Bug5.
    先来看看 Bug1, 在方法1方法2中的第一个动图, 没有导航栏的试图控制器没有导航栏的试图控制器之间的切换效果, 当动画属性置为YES后, 原本效果还不错的地方, 也产生了不友好的用户体验, 如下图:
带来的新的 Bug
...什么鬼..., 这NavigationBar 干嘛呢.... 路过一下是么? -.-!!! 体验非常不好, 再看下一个, TabBarItem 之间的切换效果: Bug5 UITabBarController 试图切换效果: UITabBarController 切换的效果
好家伙, 这玩意...不看不知道,一看吓一跳啊....每次进入我的页面的时候, 都要哆嗦一下, 这感觉太不爽了.

小结: 仅仅将动画属性置为 YES, 还是不太科学, 那再来看看方法4

方法4 [self.navigationController setNavigationBarHidden: YES animated: animated];

和刚才一样, 先来说说 方法4所解决的 Bug 吧.

  1. 方法3一样, 方法4同样解决了 Bug2Bug4.
  2. 方法4还解决了 Bug5
    与语言表达有点麻烦, 来看看下面的动图, 看看方法4所解决的 Bug:
Auto_FixBug.gif

再来看看方法4所未能解决的问题吧. Bug1Bug3:

Auto_Bugs.gif

其实方法4, 已经做的很好了, 解决了大部分的 Bug, 但是我们可以看到依然存在这两个不友好的 Bug. 接下来就给大家介绍这个究极方法.

究极方法 self.navigationController.delegate = self

先来说说写法吧, 最开始的时候, 我是写了一个继承自UINavigationController 的类, 设置代理并遵守<UINavigationController>协议, .m 文件中的3个关键方法如下:

#pragma mark - ViewController Life Circle
#pargma mark -
#Pargma mark ViewDidLoad
- (void) viewDidLoad {
  [super viewDidLoad];

  // 1. 设置代理
  self.delegate = self;
}

#pragma mark - Private Methods
#pragma mark -
#pragma mark Whether need Navigation Bar Hidden
- (BOOL) needHiddenBarInViewController:(UIViewController *)viewController {
    
    BOOL needHideNaivgaionBar = NO;
    
  // 在这里判断, 哪个 ViewController 需要隐藏导航栏, 如果有第三方的 ViewController 也需要隐藏 NavigationBar, 我们也需要在这里设置.
    if ([viewController isKindOfClass: [MLMineViewController class]] ||
        [viewController isKindOfClass: [MLUserHomePageViewController class]] ||
        [viewController isKindOfClass: [MLLoginViewController class]]) {
        needHideNaivgaionBar = YES;
    }
    
    return needHideNaivgaionBar;
}

#pragma mark - UINaivgationController Delegate
#pragma mark -
#pragma mark Will Show ViewController
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    
  // 在 NavigationController 的这个代理方法中, 设置导航栏的隐藏和显示
    [self setNavigationBarHidden: [self needHiddenBarInViewController: viewController]
                        animated: animated];
}

不否认, 这样的写法确实可行, 但是考虑到, 如果某一个第三方的ViewController 同样使用了这种方法来隐藏自己的NavigationBar, 那么就意味着将 NavigationController 的代理指向了其他的ViewController, 那么我们 App 中的所有隐藏NavigationBar 的逻辑就都失效了, 所以为了保险起见, 我将上述代码写到了MLBaseViewController 中, 并在MLBaseViewControllerViewWillAppear 方法中, 将delegate 指向了self. 代码如下:

@implementation MLBaseViewController

#pragma mark - ViewController Life Circle
#pragma mark -
#pragma mark ViewWillAppear
- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear: animated];

  // 1. 返回手势代理
  self.navigationController.interactivePopGestureRecognizer.delegate = (id)self;

  // 2. 导航控制器代理
  self.navigationController.delegate = self;
}

#pragma mark - Private Methods
#pragma mark -
#pragma mark Whether need Navigation Bar Hidden
- (BOOL) needHiddenBarInViewController:(UIViewController *)viewController {
    
    BOOL needHideNaivgaionBar = NO;
    
    if ([viewController isKindOfClass: [MLMineViewController class]] ||
        [viewController isKindOfClass: [MLUserHomePageViewController class]] ||
        [viewController isKindOfClass: [MLLoginViewController class]]) {
        needHideNaivgaionBar = YES;
    }
    
    return needHideNaivgaionBar;
}

#pragma mark - UINaivgationController Delegate
#pragma mark -
#pragma mark Will Show ViewController
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    
    [self.navigationController setNavigationBarHidden: [self needHiddenBarInViewController: viewController]
                        animated: animated];
}

@end

这样就可以避免, 第三方的ViewControllerNavigationControllerdelegate 指向了一个我们所不了解的位置.

Note1: 子类尽量不要实现 - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated方法, 当然如果你的子类实现了这个方法, 别忘了调用 super 就好了.

Note2: 在ViewWillAppear 方法中, 我们看到了一句代码:self.navigationController.interactivePopGestureRecognizer.delegate = (id)self;, 添加这句代码的原因在于: 当你自定义了NavigationBarBackButton 或 隐藏了NavigationBar之后, 系统的返回手势就失效了, 加上这句之后, 返回手势就 OK 了. 但是这句代码这样写仍然是有潜在问题的, 这会使得用户在使用 App 不当时, App 会产生一种假死的现象, 请看 PopGestureRecognizer Tips.

到这里, 其实我们已经完美的解决了上述的5个 Bug 了, 来看两张动图, 爽一下吧:

几个 UI 不友好的 Bug NavigationBar 错乱的 Bug

怎么样? 效果是不是还可以? 是不是棒棒哒?



补充内容__20160830


1、一种比较常用的导航栏隐藏显示的方法

还有一种比较常用的NavigationBar 隐藏和显示的方法. 只在ViewController 的基类里的ViewWillAppear 方法中设置NavigationBar 是否隐藏, 而ViewWillDisappear 方法中不设置导航栏是否隐藏. 这样也可以避免一些 UI上不和谐的问题. Note: 如果你遇到了一些切换ViewController 不和谐的效果, 也可以试试这种方法. 代码如下(纯手写代码, 如有拼写错误请见谅):


@implementation MLBaseViewController

#pragma mark - ViewController Life Circle
#pragma mark -
#pragma mark ViewWillAppear
- (void) viewWillAppear:(BOOL)animated {
  [super viewWillAppear: animated];

  // 1. 设置 NavigaionBar 的显示与隐藏, 这种方法只写在这个基类里就可以了, 至于哪些需要隐藏, 哪些不需要隐藏, 修改 -(void) needHideNavigationBar; 方法就 OK 了.
  [self setNavigationBarHidden: [self needHiddenBarInViewController: viewController]
                      animated: animated];
}

#pragma mark - Private Methods
#pragma mark -
#pragma mark Whether need hide navigation bar
- (BOOL) needHideNavigationBar {
  
  BOOL result = NO;

  if ([self isKindOfClass: [MLMineViewController class]] ||
      [self isKindOfClass: [MLUserHomePageViewController class]]) {
    result = YES;
  }

  return result;
}

@end

2、再谈导航栏错乱的 Bug

上文中提到的NavigationBar 错乱Bug 的解决办法, 经过深度测试发现, 当 两个隐藏 NavigationBar 的试图进行切换的时候,仍然存在. 由于项目时间紧迫, 我这里的解决办法是将其中一个页面的 NavigationBar 从原来的CustomNavigationBar 改为了系统的NavigationBar. 问题得到了暂时的解决. 希望对这个问题有研究的朋友可以一起探讨一下. 这个问题在项目不忙的时候, 我也会持续跟进.


Lemon龙说:

如果您在文章中看到了错误 或 误导大家的地方, 请您帮我指出, 我会尽快更改

如果您有什么疑问或者不懂的地方, 请留言给我, 我会尽快回复您

如果您觉得本文对您有所帮助, 您的喜欢是对我最大的鼓励

如果您有好的文章, 可以投稿给我, 让更多的 iOS Developer 在简书这个平台能够更快速的成长


上一篇: 🏠
下一篇: PopGestureRecognizer Tips

相关文章

网友评论

  • f612162c2695:我也想问下楼主,隐藏两个 NavigationBar的视图切换的时候,出现的问题有办法解决吗?
  • 洁简:self.navigationController.navigationBarHidden = NO;
    放到super之前
    [self.navigationController setNavigationBarHidden:YES animated:NO];
    放到super之后解决了无导航到无导航闪一下的问题
  • Superman168:而我目前遇到的就是的,APP偶尔会出现假死的问题,导航栏也没了,跳转很卡,很难捕捉,一直没能解决好,这个算是终极问题吗?
    Superman168:今天还遇到了一次,时不时的来一次
  • Janlor:感谢博主给与的启示,两个隐藏 NavigationBar 的控制器切换的问题只需要在设置前判断下即可解决,示例代码如下:
    即:navigationController :willShowViewController 方法内
    if ([self needHideNavigationBarViewController:viewController]) {
    [navigationController setNavigationBarHidden:YES animated:animated];
    } else if ([navigationController isNavigationBarHidden] ) {
    [navigationController setNavigationBarHidden:NO animated:animated];
    }
  • 上路喽:很好,赞一个
  • 木头Lee:可以说总结的非常全面了,正需要,感谢:pray:
  • guoshengboy:当两个隐藏 NavigationBar的试图进行切换的bug,我发现支付宝也有 不过他们判断出现时就再添加一个item解决的 我也是偶然才发现这样解决的http://www.jianshu.com/p/08cc2e14b631
  • f1e24a8d40b9:特意来回复一下 两个隐藏导航栏这个问题也困扰我几天,处理头都大了,因为这个bug刚发现时很难复现,然后把导航栏代理各种都处理一遍,后来才发现是系统问题,其实可以在导航代理里打印一下bar的items 这种情况下item其实是少了一个的,所以才会变成上一个导航的标题和左右按钮 之前几乎各种方法都试过了 有两种解决方法 1是在导航代理的didshowviewcontroller里设置 [self.navigationController setNavigationBarHidden:YES animated:YES];
    [self.navigationController setNavigationBarHidden:NO animated:YES];
    这样就能还原原来的标题了 但是会闪一下 如果能接受可以这样处理 毕竟这种情况不是很多 另一种 可以参考jznavigationextension这个第三方 他的处理方式是在 两个隐藏导航的界面 A-B,返回时候 设置 [self.navigationController setNavigationBarHidden:NO animated:NO]; 同时self.navigationbar.hidden =YES; 记得在下次push之前还原设置 [self.navigationController setNavigationBarHidden:YES animated:NO]; self.navigationbar.hidden =NO,还有一点是 用导航代理处理导航隐藏的方式用这种不行 要截获push和pop就可以 原因可能是控制器周期调用问题 我把这种方法用类别写出来 可以修复这个烦人的问题 特意来回复一下 希望可以帮助后来的人 因为被这个bug搞得快崩溃了
    洁简:闪一下如何处理
    f1e24a8d40b9:@嘸___ 隐藏有些是不需要动画的 我复制的代码动画都是YES 第一种方法动画应该是NO
  • 半邪亦正:我也遇到这个问题 纠结了很久 尤其是在半切退出又不退的情况下 很容易出现导航栏异常 包括标题字体变型 我也是醉了 比较多的是显示了上一个vc的导航栏 个人猜测是 导航栏动画和滑动返回动画冲突导致 但是仍然没有解决方案 项目代码太多 不可能全部替换为自定义导航栏
    李国安:@这个昵称已经被占用了 嗯 这篇文章我看了, 不过他的解决办法是避开了导航栏错乱的问题, 其实我认为这只是治标不治本... 还有就是我认为其实效果不是特别的好, 比如第二种解决方案, 在 Push 的时候, 会闪一下导航栏, 这个也是比较不友好的. 以上都是我自己个人的见解哈. 不过还是很感谢你提供的文章, 谢啦.
    半邪亦正:@李国安 http://www.jianshu.com/p/4b8af425a7d0 这里找到了解决方法
    李国安:@这个昵称已经被占用了 本文中提出的最后一种方法, 可以解决部分导航栏错乱的情况哈. 不能全部解决, 比如两个页面的导航栏都隐藏这种情况, 暂时没有解决.
  • MasterY:还是不行的,我也是这样做的,但是还是会出现错乱的情况。
    李国安:但是只限于 两个页面都是导航栏隐藏的情况....
  • Ataluer:项目中碰到这个问题,由于在多个页面切换过程中,都需要设置显示或隐藏导航栏,一旦因为需求改变引起页面跳转发生变化,就需要重新测试调整。所以,我最终的解决办法是。。。导航栏全部自定义。:sweat_smile:
    李国安:@Ataluer :joy::joy::joy:
  • 默默_David:楼主,我使用您的方法来隐藏导航栏,导航栏隐藏基本没有问题,但是会出现系统自带的左滑返回失效,这种情况应该怎么解决呢?
    李国安:@不会打字怎么办 http://www.jianshu.com/p/e7ccc6ca0fef 这篇文章也解决了假死的现象哟
    e777f5b18874:我也是遇到这个NavigationBar显示混乱,而且还有APP使用一段时间后会假死的情况,后面是将隐藏NavigationBar改为将NavigationBar设置为透明,就没有这个问题了
    李国安:@默默_David 看看这个能否解决您的问题: http://www.jianshu.com/p/e7ccc6ca0fef
  • guoshengboy:当两个隐藏 NavigationBar 的试图进行切换的时候,出现的问题解决了吗? :smile:
  • gyq琪琪:@上文中提到的NavigationBar 错乱Bug 的解决办法, 当两个隐藏 NavigationBar 的试图进行切换的时候,仍然存在的问题后台解决了吗
    李国安:避免两个视图控制器都隐藏导航栏 就没问题! 如果两个都隐藏的话 还没有解决!
    gyq琪琪:@gyq琪琪 后来解决没, 遇到这个问题 太坑了
  • 浅y:太感谢了 ,一直再为这个苦恼 :joy: ,终于不用加那对恶心的判定了
  • 短腿的大shu:总结的到位
    李国安:@万恶之源的大哥 3Q
  • 传递正正正能量:厉害了,我最近也是碰到。后来索性自定义了
  • dongwenbo:配合上状态栏的显示和隐藏就究极麻烦了
  • 李国安:具体怎么取消这个过渡的渐变效果我还真没研究过, 但是做到这个效果你可以让每一个 VC 拥有自己的导航栏, 就不会出现渐变的效果了, 而且据我尝试的结果, 每一个 VC 都拥有自己的导航栏, 也不会出现我上文中提到的这些 Bug 了, 个人认为这还是一个比较好的解决思路. 给你推荐个源码, 你可以研究一下: https://github.com/rickytan/RTRootNavigationController
  • Terry_L:非常感谢啊~~解决了好多问题~~不过,我还有个问题,希望解决一下: 在有Bar和有Bar之间滑动的时候,导航栏是渐变的. 我们希望导航栏和下面页面整体滑动,而不是导航栏自己渐变,而下面的页面滑动....类似于淘宝京东那样.. 如果说是在纯代码中,不是用自己画个导航栏的情况下,怎么处理? 非常希望解答一下哈.多谢啦
  • 默默_David:非常好,正为这个问题困扰着呢,mark一下,马上去试试
    李国安:@默默_David :+1: :+1: :+1: 共勉
  • LeesinS:弱弱的问一下 你的gif图片是怎么制作的
    李国安:@LeesinS 甭客气朋友
    LeesinS:@Lemon龙 OK 谢啦!
    李国安:@LeesinS Windows系统的话不太清楚! Mac的话我这边用的是一个叫做 PicGIF 的 App 制作的!
  • 16d843f652da:给个联系方式吧。微信或者QQ什么的。
    李国安:@陈P QQ:372993148
  • 16d843f652da:当两个隐藏 NavigationBar的试图进行切换的时候,导航栏错乱的 Bug还是存在的。作者对这个问题有没有研究出新的解决办法?
    李国安:@陈P 对的, 我们将系统控制的 Delegate 指向了自己的类, 所以会带来一些莫名其妙的问题. 例如: 假死之类的问题. 我在这里也做了介绍: http://www.jianshu.com/p/e7ccc6ca0fef
    刚才看到你的评论, 我突然有了一个想法, 我在第一次运行 self.navigationController.interactivePopGestureRecognizer.delegate = (id)self 这句话之前, 将系统的 delegate 保存成了一个全局变量 `globalDelegate`. 并在 MLBaseViewController 中实现的代理方法中, 使用这个全局变量`globalDelegate` 调用这个代理方法(也就是调用官方实现的代理方法), 结果依然是会出现导航栏错乱的情况. 所以我认为, 导航栏错乱跟这个设置手势代理的关系不是很大. 个人认为还是和导航栏隐藏关系比较大.
    另外: 导航栏隐藏 和 自定义返回按钮后, 返回手势之所以失效, 是因为系统实现的代理方法中 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch 这个代理方法返回了 No.
    最后: 苹果之所以在某些情况下禁用返回手势, 肯定有他的道理, 像导航栏错乱这类的问题. 否则我认为苹果没道理在导航栏隐藏的情况下, 禁用返回手势.
    以上是一些个人观点. :stuck_out_tongue_closed_eyes:
    16d843f652da:@Lemon龙 恩。最近也是遇到这个问题。我感觉我们选择隐藏导航栏,利用self.navigationController.interactivePopGestureRecognizer.delegate = (id)self这种方式来滑动返回的思路,似乎有点走偏了....就算是解决了导航栏错乱的问题,难保IOS10不会有问题,毕竟是破坏了系统的一些逻辑。 可能会有更好的解决办法吧...
    李国安:@陈P 这个问题, 我在文章的后半部分也做了更新! 最近一直忙于项目, 没有过多的时间来调研这个问题! 我这边是直接将用户个人主页的导航栏改成了原生的了(也就是说没有隐藏)
  • 十一岁的加重:最近一直被这些情况所折磨,百思不得解,感谢万分
    十一岁的加重:@Lemon龙 就是在一个隐藏了状态栏的控制器要push到一个没有隐藏导航栏的控制器时,前一个隐藏了状态栏的控制器顶部是一张大图,这样一push过去,下个控制器的导航栏,会闪一下
    十一岁的加重:@Lemon龙 好奇怪,我发现用了你的方法依然没有解决至今困扰我的问题
    李国安:@十一岁的加重 写这篇文章也是为了能对大家有点帮助, 当时遇到这个问题的时候, 确实网上也没有什么特别详细的文章.
  • qBryant:总结了基本都会出现的navbar 的bug。。。 :+1:
    李国安:@QBryant 最后那种方式确实挺不错的! 不过还是有问题没解决! 这两天我会更新!
    qBryant:@Lemon龙 viewWillAppear 里面[self.navigationController setNavigationBarHidden:YES animated:animated];
    viewWillDisappear 里面[self.navigationController setNavigationBarHidden:NO animated:animated]; 这样push的时候是没问题,但是present的时候就出现你上面跳动的bug了,看着蛋疼的一笔,用你最后面的那个方式修复了。。。非常感谢 😀
    李国安:@QBryant :stuck_out_tongue_winking_eye: 我这边出现的都已经总结到这个里面了哈

本文标题:导航栏隐藏 && 导航栏错乱

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