- 彩票10滑動移除控制器全屏實作
- 一圖示
- 二分析
- 三非全屏滑動删除的處理方式
- 四全屏滑動删除的處理方式 1 KVC
- 五全屏滑動删除的處理方式 2 delegate
彩票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[]==viewController){//根控制器
self.interactivePopGestureRecognizer.delegate = self.popGesture;
}else{
// 清空手勢代理就能實作滑動傳回, iOS6不支援
self.interactivePopGestureRecognizer.delegate = nil;
}
}
·····
@end
四、全屏滑動删除的處理方式 1 —— KVC
這種方式的處理就是,自己添加一個滑動手勢 UIPanGestureRecognizer 這個手勢的 target 和 action,使用系統手勢使用的。
那麼我們使用
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=; 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[] 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[] 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 > ;
}
完整代碼如下
//
// 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 > ;
}
@end