iOS7有个系统app都有个新功能,支持手势返回。也就是navigationViewController.interactivePopGestureRecognizer
如果你乖乖的用系统自带的UIBarButtonItem来定义navigationViewController的leftBarButtonItem的话,那么一切都ok。但是如果你是通过initWithCustomView:来定义leftBarButtonItemd的话,你需要在你父ViewController的ViewDidAppear方法里手动开启它, 当然顺便请设置好Gesture的delegate.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}
}
可是,可是,这样做还不够。你可以快速pop一个viewcontroller并且快速手势返回,这时候,你的整个屏幕就freeze了。
怎么办呢?
看了网上的整体思路就是,你当pop的时候,把navigationController.interactivePopGestureRecognizer.enabled设为NO,当你navigationController:didShowViewController:animated:(nav的delegate)时候再打开。
具体到代码就是:
在navigationViewController里
(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])self.interactivePopGestureRecognizer.enabled = NO;
[super pushViewController:viewController animated:animated];
}
在你ViewController里
- (void)navigationController:(UINavigationController *)navigationController
{didShowViewController:(UIViewController *)viewController animated:(BOOL)animate
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
}self.navigationController.interactivePopGestureRecognizer.enabled = YES;
- (void)navigationController:(UINavigationController *)navigationController
问题来了,如何令所有的navigationViewController都能有我们经过处理后的pushViewController:animated:方法。可以看到,这里我是subclass了。
这里我主要想介绍另外一种objc runtime的方法, method_swizzle。
#import <objc/runtime.h>
@implementation UINavigationController (PopGesture)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
// When swizzling a class method, use the following:
// Class class = object_getClass((id)self);
SEL originalSelector = @selector(pushViewController:animated:);
SEL swizzledSelector = @selector(xxx_pushViewController:animated:);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod =
class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
#pragma mark - Method Swizzling
- (void)xxx_pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
NSLog(@"xxx_pushViewController: %@", self);
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
self.interactivePopGestureRecognizer.enabled = NO;
[self xxx_pushViewController:viewController animated:animated];
}
@end
这样就不要subclass了。