当发生事件后,事件会被添加到UIApplication管理的事件队列中;之后UIApplication从事件队列中依次取出事件,分发到应响应的视图去处理。
视图响应事件的顺序,一般为Application-Window-Controller-View-子View。
实现方式根据hitTest与pointInSide两个方法进行分析:
1、判断该视图是否能够处理该触摸事件,如果不能,不通过pointSide方法,hittest直接返回nil
2、如果该view可以响应,则调用pointSide判断是否在视图区域,否则返回NO,同时hittest也返回nil。
3、如果步骤2中返回YES,标识在当前View中,则倒序变量该视图的子视图,直到某子视图响应,hitTest返回该子视图。
4,如果步骤3无子视图,子返回自身。
伪代码如下:
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
// 1、判断自己是否可以接收触摸事件
if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) return nil;
// 2、判断触摸点是否在自己范围内
if (![self pointInside:point withEvent:event]) return nil;
//3、倒序遍历自己的子控件,看是否子控件会响应此事件
for (NSInteger i = self.subviews.count -1 ; i >= 0 ; i --) {
UIView *subView = self.subviews[i];
//进行坐标转化
CGPoint coverPoint = [subView convertPoint:point fromView:self];
// 调用子视图的 hitTest 重复上面的步骤。找到了,返回hitTest view ,没找到返回有自身处理
UIView *hitTestView = [subView hitTest:coverPoint withEvent:event];
if (hitTestView){
return hitTestView;
}
}
//4、没有子视图响应则返回自己
return self;
}