iOS学习笔记-095.彩票10——滑动移除控制器全屏实现

彩票10——滑动移除控制器全屏实现

一、图示

这里写图片描述


二、分析

原本系统有滑动删除的,但是我们添加了放回按钮以后没有了,那么这下就尴尬了吧。那么我们就行来实现一下。

其实我们只需要把 系统手势的代理设置为nil 就可以实现这样的功能了,但是这用实现,我们是能滑动左边的并且不包含导航条。并且会产生一个bug,就是如果我们在根控制器上滑动了,那么我们就 push 不了其他控制器了。那么怎么解决呢,其实解决方式很简单,我们一开始记住我们的代理,然后在 did 控制器的时候,我们判断一下,当前的控制器是不是根控制器,如果是还原,不是赋值为nil。

另外的处理方式,就是我们自己添加一个滑动手势,然后我们使用系统的处理方法和targer来处理这个手势就行了。


三、非全屏滑动删除的处理方式

这种方式处理的结果就是只能从左侧滑动时删除。

这种方式需要添加 UINavigationControllerDelegate 代理

//
//  QWMNavigationController.m
//  03_UIView79_彩票
//
//  Created by 杞文明 on 17/8/13.
//  Copyright © 2017年 杞文明. All rights reserved.
//

#import "QWMNavigationController.h"
#import <objc/runtime.h>
@interface QWMNavigationController ()<UINavigationControllerDelegate>
/** 系统手势代理 */
@property (nonatomic, strong) id popGesture;
@end

@implementation QWMNavigationController

········

-(void)viewDidLoad{
    [super viewDidLoad];
    self.popGesture = self.interactivePopGestureRecognizer.delegate;
    self.delegate = self;
}

// 解决如果在根控制器上滑动了,不能删除的情况
-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    if(self.viewControllers[0]==viewController){//根控制器
        self.interactivePopGestureRecognizer.delegate = self.popGesture;
    }else{
        // 清空手势代理就能实现滑动返回, iOS6不支持
        self.interactivePopGestureRecognizer.delegate = nil;
    }
}

·····

@end

四、全屏滑动删除的处理方式 1 —— KVC

这种方式的处理就是,自己添加一个滑动手势 UIPanGestureRecognizer 这个手势的 targetaction,使用系统手势使用的。

那么我们使用

NSLog(@"%@",self.interactivePopGestureRecognizer);

打印一下系统手势的信息
如下

<UIScreenEdgePanGestureRecognizer: 0x7fd258d1ab20; 
    state = Possible; 
    delaysTouchesBegan = YES; 
    view = <UILayoutContainerView 0x7fd258d198a0>; 
    target= <
       (action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7fd258e1be20>)
    >
>

通过上面的信息,我们可以知道 我们 添加的手势的 action 就是 handleNavigationTransition: 方法。
但是我们 target 我们还没办法拿到。

我们使用 oc 中的 runtime 机制,来获取我们的属性名称,然后使用 KVC 来获取我们的 target

我们使用 runtime 机制打印出 UIGestureRecognizer 里面的属性

// oc  runtime 机制 只能动态获取当前类的成员属性,不能获取其子类,或者父类的属性
// __unsafe_unretained Class  要获取哪个类的成员属性
// unsigned int *outCount  获取Class 下面的所有成员属性的个数

unsigned int outCount;
Ivar * ivars = class_copyIvarList([UIGestureRecognizer class], &outCount);
for (int i=0; i<outCount; i++) {
    NSString * name = @(ivar_getName(ivars[i]));
    NSLog(@"%@",name);
}

打印结果

2017-08-26 16:21:36.885 03_UIView79_彩票[12961:57679] _gestureFlags
2017-08-26 16:21:36.885 03_UIView79_彩票[12961:57679] _targets
2017-08-26 16:21:36.885 03_UIView79_彩票[12961:57679] _delayedTouches
2017-08-26 16:21:36.886 03_UIView79_彩票[12961:57679] _delayedPresses
2017-08-26 16:21:36.886 03_UIView79_彩票[12961:57679] _view
2017-08-26 16:21:36.886 03_UIView79_彩票[12961:57679] _lastTouchTimestamp
2017-08-26 16:21:36.887 03_UIView79_彩票[12961:57679] _state
2017-08-26 16:21:36.887 03_UIView79_彩票[12961:57679] _allowedTouchTypes
2017-08-26 16:21:36.887 03_UIView79_彩票[12961:57679] _initialTouchType
2017-08-26 16:21:36.888 03_UIView79_彩票[12961:57679] _internalActiveTouches
2017-08-26 16:21:36.888 03_UIView79_彩票[12961:57679] _forceClassifier
2017-08-26 16:21:36.888 03_UIView79_彩票[12961:57679] _requiredPreviewForceState
2017-08-26 16:21:36.888 03_UIView79_彩票[12961:57679] _touchForceObservable
2017-08-26 16:21:36.888 03_UIView79_彩票[12961:57679] _touchForceObservableAndClassifierObservation
2017-08-26 16:21:36.888 03_UIView79_彩票[12961:57679] _forceTargets
2017-08-26 16:21:36.888 03_UIView79_彩票[12961:57679] _forcePressCount
2017-08-26 16:21:36.889 03_UIView79_彩票[12961:57679] _beganObservable
2017-08-26 16:21:36.889 03_UIView79_彩票[12961:57679] _failureRequirements
2017-08-26 16:21:36.889 03_UIView79_彩票[12961:57679] _failureDependents
2017-08-26 16:21:36.889 03_UIView79_彩票[12961:57679] _delegate
2017-08-26 16:21:36.889 03_UIView79_彩票[12961:57679] _allowedPressTypes
2017-08-26 16:21:36.890 03_UIView79_彩票[12961:57679] _gestureEnvironment

我们可以看到有一个 —targets 属性,然后我们 通过 KVC 获取这个值,然后打印一下。

UIScreenEdgePanGestureRecognizer * gest = self.interactivePopGestureRecognizer;

id targets = [gest valueForKeyPath:@"_targets"];

NSLog(@"%@",targets);

结果

(
    "(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7fb3c9d0b5d0>)"
)

我们可以看到 这是一个数组,但是我们还是没法知道我么的 target。

我们调试一下看一下。我们会发现原来属性叫 _target

这里写图片描述

现在我们已经知道属性名了,那么我么既可以通过 KVC 来获取了

// 通过 KVC 方式获取 _target
    id target = [targets[0] valueForKeyPath:@"_target"];

完整如下

//
//  QWMNavigationController.m
//  03_UIView79_彩票
//
//  Created by 杞文明 on 17/8/13.
//  Copyright © 2017年 杞文明. All rights reserved.
//

#import "QWMNavigationController.h"
#import <objc/runtime.h>
@interface QWMNavigationController ()<UINavigationControllerDelegate,UIGestureRecognizerDelegate>
/** 系统手势代理 */
@property (nonatomic, strong) id popGesture;
@end

@implementation QWMNavigationController

.......

-(void)viewDidLoad{
    [super viewDidLoad];

    UIScreenEdgePanGestureRecognizer * gest = self.interactivePopGestureRecognizer;

    //KVC获取 _targets 
    NSArray * targets = [gest valueForKeyPath:@"_targets"];

    // 通过 KVC 方式获取 _target
    id target = [targets[0] valueForKeyPath:@"_target"];

    //添加滑动手势
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:target action:@selector(handleNavigationTransition:)];
    [self.view addGestureRecognizer:pan];
}

@end

.......

五、全屏滑动删除的处理方式 2 ——delegate

这种处理方式,其实有原因的,我们在创建一个手势的时候,我们发现,我们添加的 target 和 delegate 是一样的,那么系统的应该也是一样的。

UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
pan.delegate = self;

所以需要的 target 其实就是delegate 。

id target = self.interactivePopGestureRecognizer.delegate;

但是如果我们这个添加了 会出现上面我们出现过的bug : 就是如果我们在根控制器上滑动了,那么我们就 push 不了其他控制器了.

那么怎么解决呢?

我们可以添加 UIGestureRecognizerDelegate 代理。手指开始时去判断是不是根控制器,如果是的话,那么我们禁止手势,如果不是我们响应手势

-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    return self.viewControllers.count > 1;
}

完整代码如下

//
//  QWMNavigationController.m
//  03_UIView79_彩票
//
//  Created by 杞文明 on 17/8/13.
//  Copyright © 2017年 杞文明. All rights reserved.
//

#import "QWMNavigationController.h"
#import <objc/runtime.h>
@interface QWMNavigationController ()<UINavigationControllerDelegate,UIGestureRecognizerDelegate>
/** 系统手势代理 */
@property (nonatomic, strong) id popGesture;
@end

@implementation QWMNavigationController
-(void)viewDidLoad{
    [super viewDidLoad];
    id target = self.interactivePopGestureRecognizer.delegate;

    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:target action:@selector(handleNavigationTransition:)];
    [self.view addGestureRecognizer:pan];
    pan.delegate = self;
}

-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    return self.viewControllers.count > 1;
}
@end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值