一、响应者链
以UIResponder作为超类的任何类都是响应者。UIView和UIControl是UIReponder的子类,因此所有视图和所有控件都是响应者。
- 初始相应器
事件首先会传递给UIApplication对象,接下来会传递给应用程序的UIWindow,UIWindow会选择一个初始相应器来处理事件。初始响应器会选择下面的方式选择1、对于触摸事件,UIWindow会确定用户触摸的视图,然后将事件交给注册了这个视图的手势识别器或则注册视图层级更高的手势识别器。只要存在能处理事件的识别器,就不会再继续找了。如果没有的话,被触摸视图就是初始相应器,事件也会传递给它。
2、对于用户摇晃设备产生的或者是来自远程遥控设备事件,将会传递给第一响应器
如果初始响应器不处理时间,它会将事件传递给它的父视图(如果存在的话),或者传递给视图控制器(如果此视图是视图控制器的视图)。如果视图控制器不处理事件,它将沿着响应器链的层级继续传给父视图控制器(如果存在的话)。
如果在整个视图层级中都没与能处理事件的视图或控制器,事件就会被传递给应用程序的窗口。如果窗口不能处理事件,而应用委托是UIResponder的子类,UIApplication对象就会将其传递给应用程序委托。最后,如果应用委托不是UIResponder的子类,或者不处理这个事件,那么这个事件将会被丢弃。
4个手势通知方法
#pragma mark - Touch Event Methods // 用户第一次触摸屏幕时被调用 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { } // 当发生某些事件(如来电呼叫)导致手势中断时被调用 - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { } // 当用户手指离开屏幕时被调用 - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { } // 当用户手指移动时触发 - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { }
二、检测扫描事件
1、手动检测
// // ViewController.m // Swipes // // Created by Jierism on 16/8/4. // Copyright © 2016年 Jierism. All rights reserved. // #import "ViewController.h" // 设置检测范围 static CGFloat const kMinimmGestureLength = 25; static CGFloat const kMaximmVariance = 5; @interface ViewController () @property (weak, nonatomic) IBOutlet UILabel *label; @property (nonatomic) CGPoint gestureStartPoint; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; self.gestureStartPoint = [touch locationInView:self.view]; } - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint currentPosition = [touch locationInView:self.view]; // 返回一个float的绝对值 CGFloat deltaX = fabsf(self.gestureStartPoint.x - currentPosition.x); CGFloat deltaY = fabsf(self.gestureStartPoint.y - currentPosition.y); // 获得两个增量后,判断用户在两个方向上移动过的距离,检测用户是否在一个方向上移动得足够远但在另一个方向移动得不够来形成轻扫动作 if (deltaX >= kMinimmGestureLength && deltaY <= kMaximmVariance) { self.label.text = @"Horizontal swipe detected"; // 2s后擦除文本 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.label.text = @""; }); }else if (deltaY >= kMinimmGestureLength && deltaX <= kMaximmVariance){ self.label.text = @"Vertical swipe detected"; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.label.text = @""; }); } } @end