事件的传递过程实际上是寻找最合适响应者过程
控制器中创建如下三个视图
RedView *redview = [[RedView alloc] initWithFrame:CGRectMake(0, 0, 300, 400)];
redview.backgroundColor = [UIColor redColor];
redview.center = self.view.center;
[self.view addSubview:redview];
BlueView *blueView = [[BlueView alloc] initWithFrame:CGRectMake(0, 150, 100, 100)];
blueView.backgroundColor = [UIColor blueColor];
[redview addSubview:blueView];
Blackview *blackview = [[Blackview alloc] initWithFrame:CGRectMake(200, 150, 100, 100)];
blackview.backgroundColor = [UIColor blackColor];
[redview addSubview:blackview];
RedView、BlueView、Blackview中分别实现如下两个方法:
#import "RedView.h"
@implementation RedView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
NSLog(@"1");
return [super hitTest:point withEvent:event];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"我是红的");
}
@end
#import "Blackview.h"
@implementation Blackview
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
return [super pointInside:point withEvent:event];
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
NSLog(@"2");
return [super hitTest:point withEvent:event];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"我是黑的");
}
#import "BlueView.h"
@implementation BlueView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
NSLog(@"3");
return [super hitTest:point withEvent:event];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"我是蓝的");
}
@end
分别点击红色区域、黑色区域、蓝色区域
Log打印如下:
点击红色:
2018-03-09 14:44:56.293861+0800 事件传递与响应链[1479:108377] 1
2018-03-09 14:44:56.294000+0800 事件传递与响应链[1479:108377] 2
2018-03-09 14:44:56.294207+0800 事件传递与响应链[1479:108377] 3
2018-03-09 14:44:56.294727+0800 事件传递与响应链[1479:108377] 我是红的
点击黑色:
2018-03-09 14:48:04.124764+0800 事件传递与响应链[1479:108377] 1
2018-03-09 14:48:04.124873+0800 事件传递与响应链[1479:108377] 2
2018-03-09 14:48:04.125326+0800 事件传递与响应链[1479:108377] 我是黑的
点击蓝色:
2018-03-09 14:49:05.530768+0800 事件传递与响应链[1524:118234] 1
2018-03-09 14:49:05.530867+0800 事件传递与响应链[1524:118234] 2
2018-03-09 14:49:05.530959+0800 事件传递与响应链[1524:118234] 3
2018-03-09 14:49:05.532497+0800 事件传递与响应链[1524:118234] 我是蓝的
事件传递流程,从self.view开始往下写
点击红色: self.view(触摸点在自己身上 从后向前遍历子控件)-redView(触摸点在自己身上 从后向前遍历子控件)- blackView(触摸点不在自己身上)-blueView(触摸点不在自己身上)-redView最合适
点击黑色: self.view(触摸点在自己身上 从后向前遍历子控件)-redview(触摸点在自己身上 从后向前遍历子控件)- blackView(触摸点在自己身上 从后向前遍历子控件)无子控件,即自身最合适
点击红色: self.view(触摸点在自己身上 从后向前遍历子控件)-redview(触摸点在自己身上 从后向前遍历子控件)- blackView(触摸点不在自己身上)-blueView(触摸点在自己身上 从后向前遍历子控件)无子控件,即自身最合适
事件传递顺序:总是从父视图向子视图传递,对于这个实验事件传递应该是UIApplication->KeyWindow->self.View->redView->blackView->blueView,对于同一个父视图下的子视图,总是先访问后添加上的子视图。
所以判断是否为最合适响应视图的定义为,触摸点在某个具备响应能力的视图上且其子视图集合a具备下列条件之一:触摸点不在a上、a无响应能力、a集合为空。
响应链:
将BlueView的touchesBegan方法注释掉
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"我是蓝的");
}
再次点击blueView,log如下:
2018-03-09 15:08:10.169678+0800 事件传递与响应链[1653:128205] 1
2018-03-09 15:08:10.169797+0800 事件传递与响应链[1653:128205] 2
2018-03-09 15:08:10.169890+0800 事件传递与响应链[1653:128205] 3
2018-03-09 15:08:10.171435+0800 事件传递与响应链[1653:128205] 我是红的
说明响应链中是由下向上传递的,当最下层没有响应方法时,信息将向上层(父视图)传递,这里blueView没有实现 touchesBegan方法,所以传向其父视图redView。更详细介绍请点击 传送门