当view被点击,事件传递过程为:
1、系统检测到手指触(Touch)操作时会将其打包成一个UIEvent对象,并放入当前活动Application的事件队列
2、UIApplication将处于任务队列最前端的事件向下分发,即UIWindow
3、UIWindow将事件向下分发,即UIView
4、UIView首先看自己是否能处理事件,触摸点是否在自己身上;能处理且触摸点在自己身上,就继续寻找子视图
5、遍历子控件,重复以上两不
6、如果没有找到,即自己最适合处理事件;若自己不能处理,则不做任何处理
UIView不接受事件处理的情况:
1、alpha < 0.01
2、userInteractionEnabled = NO
3、hidden = True
4、超出父控件区域
如何确定最适合处理事件的控件?
1、自己能响应事件
2、触摸点在自己身上
3、从后往前遍历子控件,重复上两步
4、如果没有符合条件的,那么自己就是最适合处理的
当事件传递时,会调用hitTest方法返回最合适响应的view
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
//1、如果控件不允许与用户交互,那么返回nil
if !isUserInteractionEnabled || alpha <= 0.01 || isHidden{
print("无法交互")
return nil
}
//2、如果点击的点不在当前控件中,返回nil
if !self.point(inside: point, with: event) {
return nil;
}
//3、从后往前遍历子控件
for i in (0..<subviews.count).reversed() {
print("i:",i)
let childv: UIView = subviews[i]
//当前触摸点的坐标转为相对于子控件触摸点的坐标
let childp: CGPoint = convert(point, to: childv)
//判断是否找到了更合适的子控件
let fitv = childv.hitTest(childp, with: event)
if (fitv != nil) {
return fitv
}
}
//没找到,则返回自己
return self
}