我们知道,导航控制器的边缘返回功能使用的是“UIScreenEdgePanGestureRecognizer”类配合交互式动画进行实现。
想要使用全屏滑动返回,可以通过两种方式进行实现:
- 通过苹果提供的交互式动画方式,提供动画对象和交互对象,使用UIPanGestureRecognizer对象控制交互动画的过程,实现全屏滑动返回。
- 使用自定义的UIPanGestureRecognizer对象通过KVC的方式“替换”掉原来的UIScreenEdgePanGestureRecognizer对象,使我们可以通过拖拽手势触发导航控制器原交互方法,以达到目的。
注意:本文为轻松学习之二——iOS利用Runtime自定义控制器POP手势动画的读后总结,感叹作者思路之妙。
1. 查看手势响应对象的存储方式
我们知道,手势触发是通过“target-action”方式进行。若想要进行手势替换,就需要了解手势是如何在UIGesture类内进行存储的。故我们先通过runtime的API对其一探究竟:
|
|
通过读取UIGestureRecognizer类的实例对象列表,可以查到,所有的手势响应的对象为类型为NSMutableArray的名为“_targets”的私有变量中。而对于内部真正对象的存储方式,我们需要在UIGestureRecognizer的实例中查看。现在,我们随意在UIView实例上添加一个手势,并通过以下方式查看我们定义的target和action是如何存储的:
|
|
在debug时,我们可以看到_target数组内部为target和action组成的对象,在触发手势时,运行时系统就动态地向target发送action消息完成手势响应。且由于”_targets”是数组类型,可以在运行期间动态修改内部数据。这也就为我们实现全屏手势提供了可能。
2. 探究导航控制器的返回手势
现在,我们转回到导航控制器中,使用同样方式查看其手势实例:
|
|
通过调试,可以看到,内部执行的target和action对象如下所示:
|
|
其中,target为私有类_UINavigationInteractiveTransition的实例,action为名为“handleNavigationTransition:”的SEL选择器。
3. 手势的替换
在上面,我们已经得到了边缘拖动时绑定的target和执行的SEL,现在我们只要利用runtime的动态性,将原手势与自定义的UIPanGestureRecognizer对象进行替换,使新手势绑定原target和action,并添加到原控制视图中,最后关闭原手势响应,即可完成神不知鬼不觉的“掉包”。完整代码如下:
|
|