iOS —Nav全屏滑动返回详解

iOS —Nav全屏滑动返回详解_第1张图片
一击即中.jpeg
前言:今天好好讲解一下导航栏全屏手势返回,以前只知道拿别人的来用,现在想花点时间了解其中的原理。 今天把自己学习到的分享出来,大家一起学习进步。。。
Pragma mark — NO.1 使用全屏返回的原因与技术背景
1.手机屏幕大了,没有全屏返回,用户体验感下降(虽然很多人也学还不知道大多数应用都有全屏返回功能,还傻傻的去点左上角的返回键)
2. 界面要求:
-1 : 要求在下个push出来的控制器中隐藏掉导航栏,那么我们系统自带的左侧边缘滑动返回也没有了
-2 : push出来的控制器左上角的返回键我们通常需要用按钮自定义,这种情况下也会覆盖掉左侧边缘滑动返回



Pragma mark — NO.2 简单界面搭建
1. 创建个空工程,然后在main storyboard 中给 viewController Embed in 一个navigation controller
2.自己创建一个navigation controller ,与main storyboard 中的关联起来 
3.创建一个nextViewController ,点击viewController  push 到 nextViewController .
4.在nextViewController 中隐藏 这个 navigationBar 
5.点击nextViewController 的pop按钮  pop 到 viewController
至此最简单的项目结构就创建好了(这里我们演示这个push隐藏导航栏的情况)
Pragma mark — NO.3 简要分析
#我们在自定义的nav中来看:
1.系统nav有这个左侧边缘返回的手势,说明其应该有一个Pan手势,并且有这个 target 和 action , 我们直接拿到这个手势加入到nav.view的手势中,看能否实现左划返回

@implementation JJNavigationController

- (void)viewDidLoad {
    [super viewDidLoad];
 [self.view addGestureRecognizer:self.interactivePopGestureRecognizer];
   }
//self.view:拿到push出来的控制器view
//self.interactivePopGestureRecognizer :系统给我们的导航栏pop返回手势
//运行工程,我们发现这样做是没有任何反应的

2.第二种思路:拿到系统的self.interactivePopGestureRecognizer手势中的target和action。 然后我们自己给self.view创建一个Pan(滑动手势) 将 target 和 action设置为系统的


Pragma mark — NO.4 利用runtime 取得系统手势的targer属性
#对于runtime不熟悉的伙伴,可以自行了解一下
#import "JJNavigationController.h"
#import 

@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取得系统手势的action 和 target
#通过上面的属性打印,我们可以看出@“_targets”应该是我们想要的
@implementation JJNavigationController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSArray *targets = [self.interactivePopGestureRecognizer valueForKey:@"_targets"];
    NSLog(@"targets中的东西%@",targets);
}
#打印结果
targets中的东西(
    "(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7f9210f0f2c0>)"
)
这样我们就拿到系统手势的action和target

Pragma mark — NO.6 创建Pan手势添加target和action
#获得系统的target 和 action
 NSArray *targets = [self.interactivePopGestureRecognizer valueForKey:@"_targets"];
   // NSLog(@"targets中的东西%@",targets);

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

#创建Pan手势
//创建滑动手势
    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc]initWithTarget:target action:action];
    [self.view addGestureRecognizer:panGesture];

#再次运行工程,我们会发现就已经可全屏pop返回了

  • 疑问:我们在nextViewController中没有处理过任何手势相关的东西,为什么我们拖动nextViewController的view,会有拖动手势?
    • 解惑:这其中涉及到一个响应者链问题。因为我们的nextViewController的view实际上是加在它的父控件,nav.view上的。 所以我们拖动next.view会有手势。

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

尾声:我将刘凡老师的语法糖也加入进去了,他将这个全屏返回实现写成了一个nav的分类。 技术点用的是runtime交换方法。 大家可以在理解了简单版的基础上学习一下。 可以作为以后面试官问你用runtime做过哪些事情的谈资(嘿嘿)!

你可能感兴趣的:(iOS —Nav全屏滑动返回详解)