响应链:顾名思义,是一个链条,响应传递的链条。
当我们在屏幕上点击了一个地方发生了什么?
A.用户点击屏幕,系统的RunLoop会检查到一个触摸的输入源
B.触摸的输入源会被系统封装成UIEvent对象传递给Appdelegate
C.Appdelegate向UIApplication传递事件,然后UIApplication向UIWindow传递事件
D.UIWindow会向Controller的View传递事件
E.View收到父响应者传递的事件后,递归调用- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event方法找到最合适的视图
F.如果能响应,执行它的代码 ,不能的话,递归到上一个响应者,执行响应
如果一直递归到appdelegate到都没有响应,则这次点击就被丢掉
举个栗子:
image.png
我们有四个VIew,分别为ViewA,ViewB, ViewC, ViewD.
我们在ViewA里头重写
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event
两个方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
NSLog(@"hitTest进入A_View");
UIView * view = [super hitTest:point withEvent:event];
NSLog(@"hitTest离开A_View");
return view;
}
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event {
NSLog(@"pointInsideA_view");
BOOL isInside = [super pointInside:point withEvent:event];
NSLog(@"pointInsideA_view isInside:%d",isInside);
return isInside;
}
我们在ViewB里头重写
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event
两个方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
NSLog(@"hitTest进入B_View");
UIView * view = [super hitTest:point withEvent:event];
NSLog(@"hitTest离开B_View");
return view;
}
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event {
NSLog(@"pointInsideB_view");
BOOL isInside = [super pointInside:point withEvent:event];
NSLog(@"pointInsideB_view isInside:%d", isInside);
return isInside;
}
我们在ViewC里头重写
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event
两个方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
NSLog(@"hitTest进入C_View");
UIView * view = [super hitTest:point withEvent:event];
NSLog(@"hitTest离开C_View");
return view;
}
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event {
NSLog(@"pointInsideC_view");
BOOL isInside = [super pointInside:point withEvent:event];
NSLog(@"pointInsideC_view isInside:%d", isInside);
return isInside;
}
我们在ViewD里头重写
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event
两个方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
NSLog(@"hitTest进入D_View");
UIView * view = [super hitTest:point withEvent:event];
NSLog(@"hitTest离开D_View");
return view;
}
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event {
NSLog(@"pointInsideD_view");
BOOL isInside = [super pointInside:point withEvent:event];
NSLog(@"pointInsideD_view isInside:%d",isInside);
return isInside;
}
我们点击VIewD,会得到如下Log信息
image.png
事件传递链:
ViewA--->ViewB--->ViewC--->ViewD
我们可以看到,找到了ViewD为最佳响应视觉
我们点击ViewB,会得到如下Log信息
image.png
事件传递链:
ViewA--->ViewB--->ViewC
我们可以看到,当找到ViewC的时候,ViewC没有在点击的区域,所以ViewB就是最佳的响应视觉
网友评论