参考:http://www.javashuo.com/article/p-rigmnzyj-hm.html
先执行事件链,找到合适的view,在执行响应链。
一、事件链
UIApplication -> window -> view -> view ……..->view
a. 当iOS程序中发生触摸事件后,系统会将事件加入到UIApplication管理的一个任务队列中
b. UIAplication 将处于任务队列最前端的事件向下分发,即UIWindow
c. UIWindow 将事件向下分发,即UIView
d. UIView首先看自己是否能处理事件(hidden = NO, userInteractionEnabled = YES, alpha >= 0.01),触摸点是否在自己身上。如果能,那么继续寻找子视图
e. 遍历子控件(从后往前遍历),重复上面的步骤。
f. 如果没有找到,那么自己就是事件处理着,如果自己不能处理,那就不做任何事
-
事件链的过程其实就是 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
函数的执行过程。
二、响应链
响应链是从最合适的view开始传递,处理事件传递给下一个响应者,响应链的传递是个事件链传递相反的。如果所有响应者都不处理事件,则事件被丢弃。通常获取级响应者是通过nextResponder方法的。
- 通常找到对应的view之后然后查找此view是否能处理此事件。
其实也就是看view能否依次响应下面的几个方法(并不一定是全部)来构成一个消息。
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
例如:
1.按钮上添加手势情况1
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
[btn setTitle:@"按钮" forState:UIControlStateNormal];
btn.frame = CGRectMake(40, 200, 50, 30);
btn.backgroundColor = [UIColor greenColor];
[self.view addSubview:btn];
[btn addTarget:self action:@selector(btnAction) forControlEvents:UIControlEventTouchUpInside];
UITapGestureRecognizer *tap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction1)];
[btn addGestureRecognizer:tap1];
- (void)btnAction {
NSLog(@"按钮点击的");
}
- (void)tapAction1 {
NSLog(@"手势1");
}
点击按钮后执行的结果是:
手势1
为什么呢?
由于当我们添加了UITapGestureRecognizer手势之后,当nextResponder为当前的viewcontroller时,它走touches的几个方法时先构成了tap手势的消息发送,因此打印的结果是手势1
2.按钮上添加手势情况2
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction)];
[btn addGestureRecognizer: pan];
- (void)panAction {
NSLog(@"手势");
}
给按钮上添加的是平移手势
当我们点击按钮时结果为
按钮点击的
当我们平移按钮时结果为
手势
3.按钮上添加手势情况3
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction)];
[btn addGestureRecognizer: pan];
UITapGestureRecognizer *tap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction1)];
[btn addGestureRecognizer:tap1];
[btn addTarget:self action:@selector(btnAction1) forControlEvents:UIControlEventTouchDragInside];
- (void)tapAction {
NSLog(@"手势");
}
- (void)tapAction1 {
NSLog(@"手势1");
}
- (void)btnAction1 {
NSLog(@"按钮点击的1");
}
当按钮的controlEvents为UIControlEventTouchDragInside时
,同时添加了平移和轻拍手势
当我们点击按钮时执行的是 轻拍手势
手势1
当我们平移按钮时,平移的手势和按钮的响应都执行了
按钮点击的1
手势