在iOS设备中我们必不可少的操作便是在屏幕上触摸动作和相应的手势动作,那么你的触摸和手势是如何被iOS设备所识别并且做出相应响应的呢,接下来编者将浅谈其中的奥秘。
从事件发生到其处理的对象,传递要经过特殊的一段过程。当用户点击设备屏 幕时,iOS捕捉到一系列的触摸,将其打包到UIEvent对象中并放置到应用程序 活动事件队列中。UIApplication对象从事件队列中取出最前面的事件并将其分发。通常,其发送事件给应用程序的主窗口——UIWindow实例,再由窗口对象发送事件给第一响应者 (触摸的视图)处理。
首先提到一个概念:事件响应者链,响应者链表示一系列响应者对象,响应者对象是一个能接收并处理事件的对象,UIResponser是所有响应者对象的基类,它定义了一系列编程接口(API),不但为事件处理进行服务而且还提供了通用的响应行为处理,UIApplocation,UIView,UIViewController都是直接或者间接继承自UIResponser。
响应过程:事件被交给第一响应对象处理,如果第一个响应者不处理,事件被沿着响应者链向上传递,交给下一个响应者,如果下一个响应者不处理,继续传递,如果一直没有处理,事件最后抛弃。
比如:
当用户与视图交互时,将会 消息传递给视图控制器,如果 不存在控制器,传递给父视图
如果不处理该消息,则继续 将消息向上传递
最上层的视图如果也不处理, 将事件交予Window对象
最后交由UIApplication实 例,如果不处理,丢弃事件
事件的处理方法:响应者通过复写下面的方法来监听触摸事件
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullableUIEvent *)event;//当触摸开始时调用
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullableUIEvent *)event;
//当手指移动时调用
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullableUIEvent *)event;
//当结束移动时调用
- (void)touchesCancelled:(nullableNSSet<UITouch *> *)touches withEvent:(nullableUIEvent *)event;
//当触摸取消时调用
举例:判断是单击还是双击
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//取出一根手指的触摸
UITouch *touch1 = [touches anyObject];
//触摸的次数
NSInteger count = touch1.tapCount;
if (count == 1) {
//延时调用
[self performSelector:@selector(singleTap) withObject:nil afterDelay:0.5];
} else if (count == 2) {
//取消延时调用,否则当第一次点击时就会调用上面的单击延时方法,等第一次点击0.5秒后一定会调用延时方法
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(singleTap) object:nil];
[self doubleTap];
}
}
- (void)singleTap {
NSLog(@"单击事件");
}
- (void)doubleTap {
NSLog(@"双击事件");
}
@interface ViewController () {
BOOL _isInside;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//取出一根手指的触摸
UITouch *touch1 = [touches anyObject];
//获取触摸的位置
CGPoint location = [touch1 locationInView:_blackView];
//判断当前触摸是否在黑色视图内
_isInside = [_blackView pointInside:location withEvent:nil];
}- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if (_isInside) {
//取出手指的触摸
UITouch *touch1 = [touches anyObject];
//获取触摸位置
CGPoint location = [touch1 locationInView:self.view];
//获取上一次点击时的位置
CGPoint preLocation = [touch1 previousLocationInView:self.view];
//根据两次触摸之间的位置差,来移动黑色视图
CGFloat xMove = location.x - preLocation.x;
CGFloat yMove = location.y - preLocation.y;
//移动黑色视图
CGRect frame = _blackView.frame;
frame.origin.x += xMove;
frame.origin.y += yMove;
_blackView.frame = frame;
}
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//开启多点触控
self.view.multipleTouchEnabled = YES;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if (touches.count == 2) {
//将集合转化为数组
NSArray *touchesArray = [touches allObjects];
UITouch *touch1 = touchesArray[0];
UITouch *touch2 = touchesArray[1];
//获取两个触摸点的位置
CGPoint location1 = [touch1 locationInView:self.view];
CGPoint location2 = [touch2 locationInView:self.view];
CGFloat distance2 = [self distanceFromPoint:location1 toPoint:location2];
//求前一次触摸两点之间距离
CGPoint preLocation1 = [touch1 previousLocationInView:self.view];
CGPoint preLocation2 = [touch2 previousLocationInView:self.view];
CGFloat distance1 = [self distanceFromPoint:preLocation1 toPoint:preLocation2];
//判断
if (distance1 <= distance2) {
NSLog(@"放大");
} else if(distance1 >= distance2){
NSLog(@"缩小");
}
}
}
//计算两点之间距离的方法,返回其值
- (CGFloat)distanceFromPoint:(CGPoint)point1 toPoint:(CGPoint)point2 {
return sqrt(pow(point1.x - point2.x, 2) + pow(point1.y - point2.y, 2));
}