「这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战」
事件的产生和传递
- 发生触摸事件后,系统会将该事件加入到一个由
UIApplication管理的事件队列中 UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发送事件给应用程序的主窗口(keyVindow)- 主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件,这也是整个事件处理过程的第一步
- 找到合适的视图控件后,就会调用视图控件的
touches方法来作具体的事件处理,具体方法如下:- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event; - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event; - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event; - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
示例
触摸事件的传递是从父控件传递到子控件
点击绿色view(2):UIApplication -> UIWindow -> 白色(1) -> 绿色(2)
点击蓝色view(3):UIApplication -> UIWindow -> 白色(1) -> 橙色(2) -> 蓝色(3)
点击黄色view(4):UIApplication -> UIWindow -> 白色(1) -> 橙色(2) -> 蓝色(3) -> 黄色(4)
注:
如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸事件
UIView 不接收触摸事件的三种情况
-
不接收用户交互
view.userInteractionEnabled = NO; -
隐藏
view.hidden = NO; -
透明
view.alpha = NO; -
UIImageView的userInteractionEnabled属性默认是NO,因此UIImageView以及它的子控件默认是不能接收触摸事件的
相关方法
- 寻找最合适的
view
(nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;
这两个方法是OC内部查找目标响应视图的两个方法
首先一个总体的流程为:
1.一次屏幕点击事件的产生,会产生一个点击事件 event
2.首先响应这个事件的便是 UIApplication
UIApplication将事件传递给Keywindow(UIWindow)
4.UIWindow 调用 - (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event 方法,遍历每一个子视图,查找出事件产生的视图
(这里要注意,hitTest 方法的遍历是一个倒叙遍历,满足后添加先遍历的条件)