一、系统是怎么找到第一响应者的? --只通过UIView及其子类查找
0 调用根视图的hitTtest:withEvent,其的执行过程如下:
Ie calls pointInside:withEvent:of self
If the return is NO, hitTest:withEvent: returns nil . the end of the story.
If the return is YES, it sends hitTest:withEvent: messages to its subviews. it starts from the top-level subview, and continues to other views until a subview returns a non- nil object, or all subviews receive the message.
If a subview returns a non- nil object in the first time, the first hitTest:withEvent: returns that object. the end of the story.
If no subview returns a non- nil object, the first hitTest:withEvent: returns self
三、hitTest:withEvent应用:
1)父视图中有布局重叠的且都可响应用户操作的对象,如:ScrollView and Button,如果Button在ScrollView下面,正常情况下Button是不会成为第一响应者的,如果想让Button可以响应在其布局内的触摸事件,可以在Button和ScrollView的父View中重写hitTest:withEvent方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
CGPoint hitPoint = [_testButton convertPoint:point fromView:self];
if ([_testButton pointInside:hitPoint withEvent:event])
return _testButton;
return [super hitTest:point withEvent:event];
}//_testButton是指定响应对象的 弱 引用
参考: 这里
2)UIView的子类不响应触摸事件,但其子View可以响应。通过设置userInteractionEnabled=NO,可以使UIView子类不响应触摸事件,但其会挟持子View,原因见3)
这时,可以通过重写hitTest:withEvent来实现:
-(id)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
id hitView = [super hitTest:point withEvent:event];
if (hitView == self) return nil;
else return hitView;
}
参考: 这里
3) userInteractionEnabled = NO的作用:使当前的hitTest:withEvent返回nil,其它的类似属性还有:Hidden=YES,alpha<0.01,(UIControl中Enabled=NO??),事件发生的点在子View的几何范围内,却超过了父View的几何范围( clipsToBounds=NO时可出现此种情况 )