iOS-返回手勢之無侵入性添加

首先, 起因就是被要求為一個已經(jīng)開發(fā)并上線的項目添加返回手勢, 因為本身并不熟悉項目, 所有必須使用無侵入性的方法去實現(xiàn), 實現(xiàn)的方案也是千千萬, 只是說明一下我所使用的方法, 自認為超級簡潔和方便。

1.runtime添加手勢給UIViewcontroller

最先想到的就是利用runtime添加手勢給UIViewcontroller, 而且系統(tǒng)自帶側(cè)滑手勢的回調(diào)方法handleNavigationTransition:,我們在自己的手勢上直接用它的回調(diào)方法, 大大減少了我們的代碼量和復雜度。

#import "UIViewController+popGesture.h"


@implementation UIViewController (popGesture)

+ (void)load{
    [super load];
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 假如要打開controller的統(tǒng)計 ,則把下面這行代碼打開
        __gbh_tracer_swizzleMethod([self class], @selector(loadView), @selector(newLoadView));
    });
}

- (void)newLoadView {
    [self newLoadView];
        
    id target = self.navigationController.interactivePopGestureRecognizer.delegate;
    
    // handleNavigationTransition:為系統(tǒng)私有API,即系統(tǒng)自帶側(cè)滑手勢的回調(diào)方法,我們在自己的手勢上直接用它的回調(diào)方法
    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:target action:@selector(handleNavigationTransition:)];
    panGesture.delegate = self; // 設置手勢代理,攔截手勢觸發(fā)
    [self.view addGestureRecognizer:panGesture];
    
    // 一定要禁止系統(tǒng)自帶的滑動手勢
    self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}



// 什么時候調(diào)用,每次觸發(fā)手勢之前都會詢問下代理方法,是否觸發(fā)
// 作用:攔截手勢觸發(fā)
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    // 當前控制器是根控制器時,不可以側(cè)滑返回,所以不能使其觸發(fā)手勢
    if(self.navigationController.childViewControllers.count == 1)
    {
        return NO;
    }
    
    return YES;
}

//// 允許多個手勢并發(fā)
//- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
//    return YES;
//}



// 交換方法
void __gbh_tracer_swizzleMethod(Class class, SEL originalSelector, SEL swizzledSelector){
    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);
    }
}

@end

這樣就實現(xiàn)了界面返回,是不是很簡單,不過這樣只能實現(xiàn)UIViewController界面的返回,在擁有UITableView和UIScrollview時就失效了,這是為什么呢?
因為我們的返回代碼是加載在UIViewController上,并沒有為UIScrollview添加,返回的手勢并不能傳遞到UIViewController,所以就失效了

2.處理滾動視圖手勢問題

為了無侵入依然使用分類的方法,依然我們已經(jīng)分析到原因,只需要滾動視圖將我們需要的返回手勢傳遞下去即可

#import "UIScrollView+popGesture.h"

@implementation UIScrollView (popGesture)

#define IPHONE_H [UIScreen mainScreen].bounds.size.height //屏幕的高度
#define IPHONE_W [UIScreen mainScreen].bounds.size.width // 屏幕的寬度

// 手勢事件會一直往下傳遞,不論當前層次是否對該事件進行響應。
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    
    if ([self panBack:gestureRecognizer]) {
        return YES;
    }
    return NO;
}

//location_X可自己定義,其代表的是滑動返回距左邊的有效長度
- (BOOL)panBack:(UIGestureRecognizer *)gestureRecognizer {
    
    //是滑動返回距左邊的有效長度 左1/8有效區(qū)域
    int location_X = 0.125 * IPHONE_W;
    
    if (gestureRecognizer == self.panGestureRecognizer) {
        UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)gestureRecognizer;
        CGPoint point = [pan velocityInView:pan.view];
        UIGestureRecognizerState state = gestureRecognizer.state;
        if (UIGestureRecognizerStateBegan == state || UIGestureRecognizerStatePossible == state) {
            CGPoint location = [gestureRecognizer locationInView:self];

            if (point.x > 0 && location.x < location_X && self.contentOffset.x <= 0) {
                return YES;
            }
        }
    }
    return NO;
    
}


- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    
    if ([self panBack:gestureRecognizer]) {
        return NO;
    }
    return YES;
    
}

這樣任何滾動視圖都實現(xiàn)了滑動返回,是不是很簡單,雖然不會寫作,但是都是干貨,覺得有用就給我個贊吧,你的贊就是我的動力。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,663評論 1 32
  • 翻譯自“Collection View Programming Guide for iOS” 0 關于iOS集合視...
    lakerszhy閱讀 4,076評論 1 22
  • 帶湖漂泉,大江東去,愁字了得? 這個月讀的書都非常的巧合,這樣的巧合帶來的關聯(lián)性,帶給我一些以往未曾...
    柳和梁閱讀 301評論 0 0
  • 我覺得其實關于大學生這個話題已經(jīng)說爛了,但是當我今天看到一些現(xiàn)象時,我發(fā)現(xiàn)我仍然想要說一些什么,無論是我自己,還是...
    瑾瑾陌閱讀 340評論 0 3
  • 走好人生路,確實不容易。但不要給自己太大壓力。在外打拼,的確很辛苦,要懂得犒勞自己,要吃苦,但不要太受苦。 爹娘給...
    快樂一家人_7b94閱讀 694評論 0 0

友情鏈接更多精彩內(nèi)容