iOS —Nav全屏滑動返回詳解

一擊即中.jpeg
前言:今天好好講解一下導航欄全屏手勢返回,以前只知道拿別人的來用,現在想花點時間了解其中的原理。 今天把自己學習到的分享出來,大家一起學習進步。。。
Pragma mark — NO.1 使用全屏返回的原因與技術背景
1.手機屏幕大了,沒有全屏返回,用戶體驗感下降(雖然很多人也學還不知道大多數應用都有全屏返回功能,還傻傻的去點左上角的返回鍵)
2. 界面要求:
-1 : 要求在下個push出來的控制器中隱藏掉導航欄,那么我們系統(tǒng)自帶的左側邊緣滑動返回也沒有了
-2 : push出來的控制器左上角的返回鍵我們通常需要用按鈕自定義,這種情況下也會覆蓋掉左側邊緣滑動返回



Pragma mark — NO.2 簡單界面搭建
1. 創(chuàng)建個空工程,然后在main storyboard 中給 viewController Embed in 一個navigation controller
2.自己創(chuàng)建一個navigation controller ,與main storyboard 中的關聯(lián)起來 
3.創(chuàng)建一個nextViewController ,點擊viewController  push 到 nextViewController .
4.在nextViewController 中隱藏 這個 navigationBar 
5.點擊nextViewController 的pop按鈕  pop 到 viewController
至此最簡單的項目結構就創(chuàng)建好了(這里我們演示這個push隱藏導航欄的情況)
Pragma mark — NO.3 簡要分析
#我們在自定義的nav中來看:
1.系統(tǒng)nav有這個左側邊緣返回的手勢,說明其應該有一個Pan手勢,并且有這個 target 和 action , 我們直接拿到這個手勢加入到nav.view的手勢中,看能否實現左劃返回

@implementation JJNavigationController

- (void)viewDidLoad {
    [super viewDidLoad];
 [self.view addGestureRecognizer:self.interactivePopGestureRecognizer];
   }
//self.view:拿到push出來的控制器view
//self.interactivePopGestureRecognizer :系統(tǒng)給我們的導航欄pop返回手勢
//運行工程,我們發(fā)現這樣做是沒有任何反應的

2.第二種思路:拿到系統(tǒng)的self.interactivePopGestureRecognizer手勢中的target和action。 然后我們自己給self.view創(chuàng)建一個Pan(滑動手勢) 將 target 和 action設置為系統(tǒng)的


Pragma mark — NO.4 利用runtime 取得系統(tǒng)手勢的targer屬性
#對于runtime不熟悉的伙伴,可以自行了解一下
#import "JJNavigationController.h"
#import <objc/runtime.h>

@interface JJNavigationController ()

@end

@implementation JJNavigationController

- (void)viewDidLoad {
    [super viewDidLoad];

    //1.通過運行時,打印手勢中的所有屬性
    unsigned int count = 0;
    //拷貝所有關于手勢的屬性,包含私有屬性
    Ivar *ivars = class_copyIvarList([UIGestureRecognizer class], &count);
    //遍歷這個屬性數組,拿到每一個屬性
    NSArray *ivarList = [NSArray array];
    //初始化一個count那么長的可變數組
    NSMutableArray *mutableList = [NSMutableArray arrayWithCapacity:count];
    for (unsigned int i = 0; i < count; i++) {
        //獲取成員變量名
        const char *ivarName = ivar_getName(ivars[i]);
        //獲取類的成員變量的類型
        //const char *ivarType = ivar_getTypeEncoding(ivars[i]);
    [mutableList addObject:[NSString stringWithUTF8String:ivarName]];
    }
    //釋放
    
    free(ivars);
    
    ivarList = [NSArray arrayWithArray:mutableList];
    
    NSLog(@"手勢所有屬性名--%@",ivarList);
}

#打印結果:
Nav全屏手勢返回[1773:90512] 手勢所有屬性名--(
    "_gestureFlags",
    "_targets",
    "_delayedTouches",
    "_delayedPresses",
    "_view",
    "_lastTouchTimestamp",
    "_state",
    "_allowedTouchTypes",
    "_initialTouchType",
    "_internalActiveTouches",
    "_forceClassifier",
    "_requiredPreviewForceState",
    "_touchForceObservable",
    "_touchForceObservableAndClassifierObservation",
    "_forceTargets",
    "_forcePressCount",
    "_beganObservable",
    "_failureRequirements",
    "_failureDependents",
    "_delegate",
    "_allowedPressTypes",
    "_gestureEnvironment"
)
Pragma mark — NO.5 通過KVC取得系統(tǒng)手勢的action 和 target
#通過上面的屬性打印,我們可以看出@“_targets”應該是我們想要的
@implementation JJNavigationController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSArray *targets = [self.interactivePopGestureRecognizer valueForKey:@"_targets"];
    NSLog(@"targets中的東西%@",targets);
}
#打印結果
targets中的東西(
    "(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7f9210f0f2c0>)"
)
這樣我們就拿到系統(tǒng)手勢的action和target

Pragma mark — NO.6 創(chuàng)建Pan手勢添加target和action
#獲得系統(tǒng)的target 和 action
 NSArray *targets = [self.interactivePopGestureRecognizer valueForKey:@"_targets"];
   // NSLog(@"targets中的東西%@",targets);

    id target = [targets.firstObject valueForKey:@"target"];
    SEL action = NSSelectorFromString(@"handleNavigationTransition:");

#創(chuàng)建Pan手勢
//創(chuàng)建滑動手勢
    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc]initWithTarget:target action:action];
    [self.view addGestureRecognizer:panGesture];

#再次運行工程,我們會發(fā)現就已經可全屏pop返回了

  • 疑問:我們在nextViewController中沒有處理過任何手勢相關的東西,為什么我們拖動nextViewController的view,會有拖動手勢?
    • 解惑:這其中涉及到一個響應者鏈問題。因為我們的nextViewController的view實際上是加在它的父控件,nav.view上的。 所以我們拖動next.view會有手勢。

完整項目地址: nav全屏返回

尾聲:我將劉凡老師的語法糖也加入進去了,他將這個全屏返回實現寫成了一個nav的分類。 技術點用的是runtime交換方法。 大家可以在理解了簡單版的基礎上學習一下。 可以作為以后面試官問你用runtime做過哪些事情的談資(嘿嘿)!
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容