前因
人活一辈子,总要遇上一些事情。
拿我自己来说
便是实现iOS全屏右滑返回。
我开始参考的是啊崢的文章
【8行代码教你搞定导航控制器全屏滑动返回效果】
实现起来却是遇上了不少问题,因为手势代理方法做的判断不够完善,还有好几个情况下触发手势导致bug出现。
总的来说有三种情况下手势不应该执行:
- 当前controller是rootViewController时
- pop动画正在进行时
- 左滑时
另外。
该文采取的办法是对navigationController自带的interactivePopGestureRecognizer下手,禁用interactivePopGestureRecognizer,给interactivePopGestureRecognizer的delegate换上自定义的UIPanGestureRecognizer。
是否有更简单的办法?有的。
// 更换interactivePopGestureRecognizer的delegate
// 这里设置为navigationController自己
self.interactivePopGestureRecognizer.delegate = self;
// 自带的边缘返回手势的类是UIScreenEdgePanGestureRecognizer,只负责edge部分
// 那么换成包容心更强的UIPanGestureRecognizer
object_setClass(self.interactivePopGestureRecognizer, [UIPanGestureRecognizer class]);
可是还是喜欢拿来主义。
于是在github上找到:
sunnyxxx的FDFullscreenPopGesture
sunnyxxx已经封装得很完美了,完全AOP。在其手势代理方法中,除了上面提到的三种情况,还增加了两种情况,通过设置controller的两个属性控制手势。
- fd_interactivePopDisabled:可单独关闭某个controller的滑动返回手势
- fd_interactivePopMaxAllowedInitialDistanceToLeftEdge:自定义手势范围。
拿来主义真好。
我把代码改了下,对delegate下手,代码如下。
// if (![self.interactivePopGestureRecognizer.view.gestureRecognizers containsObject:self.fd_fullscreenPopGestureRecognizer]) {
//
// // Add our own gesture recognizer to where the onboard screen edge pan gesture recognizer is attached to.
// [self.interactivePopGestureRecognizer.view addGestureRecognizer:self.fd_fullscreenPopGestureRecognizer];
//
// // Forward the gesture events to the private handler of the onboard gesture recognizer.
// NSArray *internalTargets = [self.interactivePopGestureRecognizer valueForKey:@"targets"];
// id internalTarget = [internalTargets.firstObject valueForKey:@"target"];
// SEL internalAction = NSSelectorFromString(@"handleNavigationTransition:");
// self.fd_fullscreenPopGestureRecognizer.delegate = self.fd_popGestureRecognizerDelegate;
// [self.fd_fullscreenPopGestureRecognizer addTarget:internalTarget action:internalAction];
//
// // Disable the onboard gesture recognizer.
// self.interactivePopGestureRecognizer.enabled = NO;
// }
if ([self.interactivePopGestureRecognizer isKindOfClass:[UIScreenEdgePanGestureRecognizer class]]) {
object_setClass(self.interactivePopGestureRecognizer, [UIPanGestureRecognizer class]);
self.interactivePopGestureRecognizer.delegate = self.fd_popGestureRecognizerDelegate;
}
后果
再也不需要自定义手势+截图实现返回转场那种老方法了。