在OC开发中,导航控制器是一个非常常见的控件,而且在不少使用时候,我们需要自定义导航条NavigationBar。但是这个做法可能带来一些小麻烦,下面是我遇到的问题以及解决方案的思维过程。
在苹果内部,返回功能的实现自带了一个边缘的滑动返回功能。但是一旦使用我们自定义的NavigationBar,重写了返回按钮,子控制器这个功能便会消失。如果我们既要用到自定义,又要保留滑动返回功能,那我们首先要分析消失的原因,再来寻找解决方案。
既然替换NavigationBar会导致滑动返回功能的消失,那我们基本可以确定,在NavigationBar当中会有某些属性某些方法实现了这个功能。那么需要进一步考虑系统做了哪些事,哪些会导致滑动功能失效。
由于滑动功能肯定需要手势,我们可以先从手势进行分析。又因为滑动返回手势是iOS7.0以后推出的,而且添加手势是添加到UINavigationController的view上,那我们直接点进去搜索关键字“gesture”
出现有且只有一个符合我们条件的属性。那我们可以大胆推测滑动返回功能跟interactivePopGestureRecognizer有关系,所以直接打印它的值来观察。
刚好它的值中有个与屏幕边缘的手势相关,进一步验证我们的猜想。那么就可以用最简单粗暴的方法来确认,直接“干掉”该方法,如果功能失效,那肯定与它相关,那我们可以考虑尝试代理,通过interactivePopGestureRecognizer让滑动返回功能失效。首先让控制器成为interactivePopGestureRecognizer的代理,在代理方法中把识别手势方法的返回值改为NO,不出所料,滑动功能无法实现。
为了确认该属性本来就存在着代理,顺便把代理属性的值也打印出来。
这也可以证明了猜想的正确性。那么下一步就是考虑如何在使用自定义导航条(NavigationBar)的基础上,使滑动功能继续实现。
首先尝试直接把代理属性清空,不让它继续控制屏幕滑动,确实实现了自定义NavigationBar后继续滑动的返回功能。但明显也会带来bug,造成导航控制器view也可以滑动,而且滑动后造成了界面的假死,所以不能把代理设置为nil。那我们继续使用控制器作为代理,考虑通过控制手势在根控制器上不能滑动来修复该bug。
在手势控制时加入判断,如果该控制器为根控制器,那么手势将不会触发,如果为子控制器,能够正常使用。最终达到项目要求,在使用自定义NavigationBar自定义返回按钮的前提下实现原有的滑动返回功能。