类别定义pop返回手势

链接:http://pan.baidu.com/s/1nvzrBfj

.h

#import <UIKit/UIKit.h>

@interface UINavigationController (XYFullscreenPopGesture)



@end


@interface UIViewController (XYFullscreenPopGesture)

/**
 *  是否隐藏导航栏
 */
@property (nonatomic, assign) BOOL xy_prefersNavigationBarHidden;

/**
 *  手势是否禁用
 */
@property (nonatomic, assign) BOOL xy_interactivePopDisabled;

@end

.m

#import "UINavigationController+XYFullscreenPopGesture.h"
#import <objc/runtime.h>

//手势代理实现
@interface _XYFullscreenPopGestureRecognizerDelegate : NSObject <UIGestureRecognizerDelegate>

@property (nonatomic, weak) UINavigationController *navigationController;

@end

@implementation _XYFullscreenPopGestureRecognizerDelegate

- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer{
    //只有一个视图控制器时,返回NO
    if (self.navigationController.viewControllers.count <= 1) {
        return NO;
    }
    //手势禁用时,返回NO
    UIViewController *topViewController = self.navigationController.viewControllers.lastObject;
    if (topViewController.xy_interactivePopDisabled) {
        return NO;
    }
    //正在执行手势,时返回NO
    if ([[self.navigationController valueForKey:@"_isTransitioning"] boolValue]) {
        return NO;
    }
    //手势相反时,返回NO
    CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view];
    if (translation.x <= 0) {
        return NO;
    }
    return YES;
}

@end



typedef void (^_XYViewControllerWillAppearInjectBlock)(UIViewController *viewController, BOOL animated);

@interface UIViewController (XYFullscreenPopGesturePrivate)

@property (nonatomic, copy) _XYViewControllerWillAppearInjectBlock xy_willAppearInjectBlock;

@end

@implementation UIViewController (XYFullscreenPopGesturePrivate)
+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];

        SEL originalSelector = @selector(viewWillAppear:);
        SEL swizzledSelector = @selector(xy_viewWillAppear:);

        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

        BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
        if (success) {
            class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}
//将要消失的时候
- (void)xy_viewWillAppear:(BOOL)animated{
    [self xy_viewWillAppear:animated];
    if (self.xy_willAppearInjectBlock) {
        self.xy_willAppearInjectBlock(self,animated);
    }
}
//消失回调block
- (_XYViewControllerWillAppearInjectBlock)xy_willAppearInjectBlock{
    return objc_getAssociatedObject(self, _cmd);
}
- (void)setXy_willAppearInjectBlock:(_XYViewControllerWillAppearInjectBlock)xy_willAppearInjectBlock{
    objc_setAssociatedObject(self, @selector(xy_willAppearInjectBlock), xy_willAppearInjectBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

@end

@implementation UINavigationController (XYFullscreenPopGesture)


+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class aClass = [self class];

        SEL originalSelector = @selector(pushViewController:animated:);
        SEL swizzledSelector = @selector(xy_pushViewController:animated:);

        Method originalMethod = class_getInstanceMethod(aClass, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(aClass, swizzledSelector);


        BOOL success =
        class_addMethod(aClass,
                        originalSelector,
                        method_getImplementation(swizzledMethod),
                        method_getTypeEncoding(swizzledMethod));

        if (success) {
            class_replaceMethod(aClass,
                                swizzledSelector,
                                method_getImplementation(originalMethod),
                                method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        } 
    });
}
- (void)xy_pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
    if (![self.interactivePopGestureRecognizer.view.gestureRecognizers containsObject:self.xy_fullscreenPopGestureRecognizer]) {
        //不包含手势时,添加手势
        [self.interactivePopGestureRecognizer.view addGestureRecognizer:self.xy_fullscreenPopGestureRecognizer];
        /**
         *  获取系统手势的target数组
         */
        NSArray* _targets = [self.interactivePopGestureRecognizer valueForKey:@"targets"];
        /**
         *  获取它的唯一对象,我们知道它是一个叫UIGestureRecognizerTarget的私有类,它有一个属性叫_target
         */
        id gestureRecognizerTarget = [_targets firstObject];
        /**
         *  获取_target:_UINavigationInteractiveTransition,它有一个方法叫handleNavigationTransition:
         */
        id internalTarget = [gestureRecognizerTarget valueForKey:@"target"];
        /**
         *  通过前面的打印,我们从控制台获取出来它的方法签名。
         */
        SEL internalAction = NSSelectorFromString(@"handleNavigationTransition:");
        /**
         *  创建一个与系统一模一样的手势,我们只把它的类改为UIPanGestureRecognizer
         */
        self.xy_fullscreenPopGestureRecognizer.delegate = self.xy_popGestureRecognizerDelegate;
        [self.xy_fullscreenPopGestureRecognizer addTarget:internalTarget action:internalAction];
        //禁用系统手势
        self.interactivePopGestureRecognizer.enabled = NO;
    }
    [self xy_setupViewControllerBasedNavigationBarAppearanceIfNeeded:viewController];
    //调用pushViewController:animated:
    if (![self.viewControllers containsObject:viewController]) {
        [self xy_pushViewController:viewController animated:animated];
    }
}
- (void)xy_setupViewControllerBasedNavigationBarAppearanceIfNeeded:(UIViewController *)appearingViewController{
    //设置
    __weak typeof(self) weakSelf = self;
    _XYViewControllerWillAppearInjectBlock block = ^(UIViewController* viewController,BOOL animated){
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (strongSelf) {
            [strongSelf setNavigationBarHidden:viewController.xy_prefersNavigationBarHidden animated:animated];
        }
    };
    appearingViewController.xy_willAppearInjectBlock = block;
    UIViewController *disappearingViewController = self.viewControllers.lastObject;
    if (disappearingViewController && !disappearingViewController.xy_willAppearInjectBlock) {
        disappearingViewController.xy_willAppearInjectBlock = block;
    }
}
//关联手势
- (UIPanGestureRecognizer *)xy_fullscreenPopGestureRecognizer
{
    UIPanGestureRecognizer *panGestureRecognizer = objc_getAssociatedObject(self, _cmd);

    if (!panGestureRecognizer) {
        panGestureRecognizer = [[UIPanGestureRecognizer alloc] init];
        panGestureRecognizer.maximumNumberOfTouches = 1;
        objc_setAssociatedObject(self, _cmd, panGestureRecognizer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return panGestureRecognizer;
}
- (_XYFullscreenPopGestureRecognizerDelegate *)xy_popGestureRecognizerDelegate{
    _XYFullscreenPopGestureRecognizerDelegate* delegate = objc_getAssociatedObject(self, _cmd);
    if (!delegate) {
        delegate = [[_XYFullscreenPopGestureRecognizerDelegate alloc]init];
        delegate.navigationController = self;
        objc_setAssociatedObject(self, _cmd, delegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return delegate;
}
@end
@implementation UIViewController (XYFullscreenPopGesture)
//是否隐藏导航栏
- (BOOL)xy_prefersNavigationBarHidden{
    return objc_getAssociatedObject(self, _cmd);
}
- (void)setXy_prefersNavigationBarHidden:(BOOL)xy_prefersNavigationBarHidden{
    objc_setAssociatedObject(self, @selector(xy_prefersNavigationBarHidden), @(xy_prefersNavigationBarHidden), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
//手势是否禁用
- (BOOL)xy_interactivePopDisabled{
    return [objc_getAssociatedObject(self, _cmd) boolValue];
}
- (void)setXy_interactivePopDisabled:(BOOL)xy_interactivePopDisabled{
    objc_setAssociatedObject(self, @selector(xy_interactivePopDisabled), @(xy_interactivePopDisabled), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaoxiaobukuang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值