Lottery 10-Sliding Removal Controller Full Screen Implementation
I. illustration
Two, analysis
The original system has sliding deletion, but we added the playback button after no, then this is embarrassing. Then we can do it.
In fact, we only need to set the agent of the system gesture to nil to achieve such a function, but with this implementation, we can slide to the left without the navigation bar. And there's a bug that if we slide on the root controller, then we can't push other controllers. So how to solve it? In fact, the solution is very simple. We remember our agent at first, and then when did controller, we judge whether the current controller is the root controller, and if it is restored, it is not assigned to nil.
Another way to deal with this is to add a sliding gesture ourselves, and then we can use the system's processing method and targer to deal with this gesture.
3. Processing methods of non-full-screen sliding deletion
The result of this approach is that it can only be deleted when sliding from the left.
This approach requires adding UINavigation Controller Delegate agents
//
// QWMNavigationController.m
// 03_UIView79_Lottery
//
// Created by Qi Civilization on 17/8/13.
// Copyright 2017 Qi Civilization. All rights reserved.
//
#import "QWMNavigationController.h"
#import <objc/runtime.h>
@interface QWMNavigationController ()<UINavigationControllerDelegate>
/** System Gesture Agent */
@property (nonatomic, strong) id popGesture;
@end
@implementation QWMNavigationController
········
-(void)viewDidLoad{
[super viewDidLoad];
self.popGesture = self.interactivePopGestureRecognizer.delegate;
self.delegate = self;
}
// Solve the problem that if you slide on the root controller, you can't delete it.
-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
if(self.viewControllers[0]==viewController){//Root controller
self.interactivePopGestureRecognizer.delegate = self.popGesture;
}else{
// Clear gesture agent can achieve sliding return, iOS6 does not support
self.interactivePopGestureRecognizer.delegate = nil;
}
}
·····
@end
4. Processing Method of Full Screen Sliding Delete 1-KVC
In this way, you add a sliding gesture UIPanGesture Recognizer to the target and action of the gesture and use the system gesture.
So let's use
NSLog(@"%@",self.interactivePopGestureRecognizer);
Print out the system gesture information
as follows
<UIScreenEdgePanGestureRecognizer: 0x7fd258d1ab20;
state = Possible;
delaysTouchesBegan = YES;
view = <UILayoutContainerView 0x7fd258d198a0>;
target= <
(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7fd258e1be20>)
>
>
From the above information, we can see that the action of the gesture we added is handleNavigation Transition: Method.
But we haven't got the target yet.
We use the runtime mechanism in oc to get our attribute names, and then use KVC to get our target
We use the runtime mechanism to print out the attributes in UIGesture Recognizer
// The OC runtime mechanism can only dynamically acquire the membership attributes of the current class, but cannot acquire the attributes of its subclass or parent class.
// _ unsafe_unretained Class to obtain which class's member properties
// unsigned int *outCount gets the number of all member attributes under 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);
}
Print results
2017-08-26 16:21:36.885 03_UIView79_Lottery [12961:57679]_gesture Flags 2017-08-26 16:21:36.885 03_UIView79_Lottery [12961:57679]_targets 2017-08-26 16:21:36.885 03_UIView79_Lottery [12961:57679]_delayed Touches 2017-08-26 16:21:36.886 03_UIView79_Lottery [12961:57679]_delayed Presses 2017-08-26 16:21:36.886 03_UIView79_Lottery [12961:57679]_view 2017-08-26 16:21:36.886 03_UIView79_Lottery [12961:57679]_lastTouch Timestamp 2017-08-26 16:21:36.887 03_UIView79_Lottery [12961:57679]_state 2017-08-26 16:21:36.887 03_UIView79_Lottery [12961:57679]_allowed TouchTypes 2017-08-26 16:21:36.887 03_UIView79_Lottery [12961:57679]_initial TouchType 2017-08-26 16:21:36.888 03_UIView79_Lottery [12961:57679]_Internal Active Touches 2017-08-26 16:21:36.888 03_UIView79_Lottery [12961:57679]_force Classifier 2017-08-26 16:21:36.888 03_UIView79_Lottery [12961:57679]_requiredPreview Force State 2017-08-26 16:21:36.888 03_UIView79_Lottery [12961:57679]_Touch Force Observable 2017-08-26 16:21:36.888 03_UIView79_Lottery [12961:57679]_Touch Force Observable AndClassifier Observation 2017-08-26 16:21:36.888 03_UIView79_Lottery [12961:57679]_force Targets 2017-08-26 16:21:36.888 03_UIView79_Lottery [12961:57679]_forcePress Count 2017-08-26 16:21:36.889 03_UIView79_Lottery [12961:57679]_began Observable 2017-08-26 16:21:36.889 03_UIView79_Lottery [12961:57679]_Failure Requirements 2017-08-26 16:21:36.889 03_UIView79_Lottery [12961:57679]_Failure Dependents 2017-08-26 16:21:36.889 03_UIView79_Lottery [12961:57679]_delegate 2017-08-26 16:21:36.889 03_UIView79_Lottery [12961:57679]_allowedPressTypes 2017-08-26 16:21:36.890 03_UIView79_Lottery [12961:57679]_gesture Environment
We can see that there is a - target attribute, and then we get this value through KVC, and print it out.
UIScreenEdgePanGestureRecognizer * gest = self.interactivePopGestureRecognizer;
id targets = [gest valueForKeyPath:@"_targets"];
NSLog(@"%@",targets);
Result
(
"(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7fb3c9d0b5d0>)"
)
We can see that this is an array, but we still can't know our target.
Let's debug it and have a look. We will find that the original attribute is called _target.
Now that we know the attribute name, we can get it through KVC.
// Getting _target by KVC
id target = [targets[0] valueForKeyPath:@"_target"];
Complete as follows
//
// QWMNavigationController.m
// 03_UIView79_Lottery
//
// Created by Qi Civilization on 17/8/13.
// Copyright 2017 Qi Civilization. All rights reserved.
//
#import "QWMNavigationController.h"
#import <objc/runtime.h>
@interface QWMNavigationController ()<UINavigationControllerDelegate,UIGestureRecognizerDelegate>
/** System Gesture Agent */
@property (nonatomic, strong) id popGesture;
@end
@implementation QWMNavigationController
.......
-(void)viewDidLoad{
[super viewDidLoad];
UIScreenEdgePanGestureRecognizer * gest = self.interactivePopGestureRecognizer;
//KVC Gets _targets
NSArray * targets = [gest valueForKeyPath:@"_targets"];
// Getting _target by KVC
id target = [targets[0] valueForKeyPath:@"_target"];
//Add sliding gestures
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:target action:@selector(handleNavigationTransition:)];
[self.view addGestureRecognizer:pan];
}
@end
.......
5. Processing Method of Full Screen Sliding Delete 2 - delegate
There's a reason for this. When we create a gesture, we find that the target we add is the same as the delegate, so the system should be the same.
as
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
pan.delegate = self;
So the target you need is actually delegate.
id target = self.interactivePopGestureRecognizer.delegate;
But if we add this, we'll have the bug we've seen above: if we slide on the root controller, then we can't push other controllers.
So how to solve it?
We can add UIGesture Recognizer Delegate agent. Fingers start by deciding if it's the root controller. If so, we forbid gestures, if not our response gestures.
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
return self.viewControllers.count > 1;
}
The complete code is as follows
//
// QWMNavigationController.m
// 03_UIView79_Lottery
//
// Created by Qi Civilization on 17/8/13.
// Copyright 2017 Qi Civilization. All rights reserved.
//
#import "QWMNavigationController.h"
#import <objc/runtime.h>
@interface QWMNavigationController ()<UINavigationControllerDelegate,UIGestureRecognizerDelegate>
/** System Gesture Agent */
@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