iOS中事件的产生和传递

291 阅读2分钟

「这是我参与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;
    

示例

Snip20211124_7.png

触摸事件的传递是从父控件传递到子控件

点击绿色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;
    
  • UIImageViewuserInteractionEnabled 属性默认是 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

  1. UIApplication 将事件传递给 Keywindow(UIWindow)

4.UIWindow 调用 - (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event 方法,遍历每一个子视图,查找出事件产生的视图

(这里要注意,hitTest 方法的遍历是一个倒叙遍历,满足后添加先遍历的条件)