看了滑动返回的代码,总觉得没有完全理解,虽然可以囫囵吞枣照搬使用,但又觉得不妥,看了别人的解释又大体相似,归根到底是由于其中有一些细节之处没有搞清楚,深思之后,把自己的理解及时写下来,以备翻看
首先明确滑动返回功能:是由导航控制器的交互性弹出手势识别器:self.interactivePopGestureRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:_UINavigationInteractiveTransition的对象 action:@selector(handleNavigationTransition:)在初始化创建的时候指定了--系统私有对象--响应拖动手势事件--去执行处理导航切换这个方法handleNavigationTransition
如何确定是这样创建的呢?
打印self.interactivePopGestureRecognizer,进行内部实现模拟
问题1:既然这个手势识别器对象存在,系统的私有对象和方法这个不用担心,必然存在,可是为什么还是无效呢?
猜测:可能有一个方法控制拖动事件没有响应,注意上方用--隔开的满足条件
思路:按照以往的规律,target和delegate都可以响应外部事件,那么这个手势识别器是否还设置了delegate?,打印后确实如此,那么可以肯定它的代理对象执行了某个代理方法去控制判断:如果是自定义了返回按钮,那么这个手势识别器就不接收UITouch这个拖动手势对象,或者说不接收拖动事件,这个方法类似于一个开关,方法内部进行了判断,大概是这样:if(self.navigationItem.leftBarButtonItem) return NO;
注意:手势识别器即UIPanGestureRecognizer不是手势,它是管理手势的类,UITouch才是手势
测试:如果不执行这个代理方法,这个判断就无效了,这个开关也就不起作用了,那么最直接的做法是:self.self.interactivePopGestureRecognizer.delegate = nil;这样handleNavigationTransition这个方法又可以默认执行了
问题2: 设置代理为nil后,在根控制器下,滑动返回,处于假死状态,这又是什么原因导致的?
原因:根控制器下,依然可以默认响应滑动返回上级事件,这显然是不合理的,系统处于内部保护,终止了这种做法
区别:默认返回按钮,在根控制器下,为什么不会假死?
思路:那个代理方法既然起开关作用,决定什么情况下响应,那么它还应该做了一个判断条件,就是根控制器下不起作用,非根控制器才起作用,而刚才已经为nil,但又不能用系统提供的代理,只能自己重写这个方法,进行手动控制
解决:如果导航控制器中要实现代理方法,那么需要设置代理为当前导航控制器对象,遵守代理协议<UIGestureRecognizerDelegate>
1.self.self.interactivePopGestureRecognizer.delegate = self
2.-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
return self.childViewControllers.count > 1;
}
总结:1. self.interactivePopGestureRecognizer既可以使用target,又可以使用delegate,但是指定的对象实现的方法功能不一样,一个是进行返回切换,一个是控制什么时候才可以切换,这个类的使用还真是特别,让人耳目一新,原来还可以这样搞
2. 上面的代理方法,系统默认进行了两个判断,一个是是否设置了leftBarButtonItem ,另一个是是否是根控制器,如果都为是,那么控制切换不执行
感悟:学习后的思考总是一个煎熬的过程,耗时又耗力,但又心知欲速则不达,没有理解清楚的地方,埋下的坑,又会产生一个心理负担,过后还会偶然想起,但又不通透,索性花点时间总结一下
路过的大侠,还望指出不足之处!