iOS PushViewController 时使用返回手势页面卡死的问题

记录遇到的一个神奇BUG、以及它的解决办法

问题描述

如果当前的ViewController是Navgation的rootViewController的情况下,点击Push到另一个页面时候,立即左滑返回,页面会卡死、并且会发生一些诡异的事情

  • 有时Tabbar会消失、在这个阶段ViewController还没有被Push出来 继续使用左滑返回手势的话,页面会从右边慢慢滑出来
  • 有时ViewController确实被push出来显示在界面上了、但是啥都点不了了。界面卡死、但是并没有发生崩溃、或者内存、CPU占用异常的情况 这个时候进入视图层级会发现在页面的最上层,有一个叫做 _UIParallaxDimmingView 的视图挡在了Window上,拦截掉了你所有的点击事件

层级展示

这个 _UIParallaxDimmingView 是一个私有类、我找了一通并没有发现相关的文档说明它具体是个什么东西,只能从名称上来猜测这是控制Push和Pop时左侧的渐渐暗度变化的一个东西 那么我们遇到的问题估计就是下面的这个过程:

  • 当页面开始push后navgation会启用_UIParallaxDimmingView作为临时页面过渡动画、这时navigation的左滑已经启用,立即返回后_UIParallaxDimmingView会来不及删除,导致它留在页面上卡死了所有的响应

那么知道这个东西大概和返回手势有关系过后大概也就知道怎么解决它了

解决办法

在Navgation的基类或者runtime或者category之类的 总之在Navgation 的delegate 在show到第二个页面时,也就是下面这个代理执行的时候

1
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;

检测当前的Controller是否是Navigation的rootViewController 然后动态关闭开启 左滑手势

1
2
3
4
5
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.interactivePopGestureRecognizer.enabled = self.viewControllers.count > 1;
}
}

问题解决