iOS Button 被点击发生了什么?

873 阅读2分钟

Button 被点击之后,分为两部分:一个是事件的传递,一个是响应的传递.即传递链响应链.

大体意思就是:先找点的是哪个view,然后再决定由哪个view来响应这个事件.

首先我们来看传递链:

传递链中有两个核心的方法:

- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;   // recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;   // default returns YES if point is in bounds

hitTest 会返回一个View,用来寻找到底哪一个view来响应. pointInside 来判断当前的点是否存在某个视图内部.

当alpha = 0 或者 hidden = Yes 或者 userInter 属性为NO 的时候都是不处理事件的.

事件传递流程: 1.将点击事件加到Applicaton维护的任务队列中,然后取最顶部的事件进行处理,向下分发.

2.来到window,然后就开始递归调用hitTest 来寻找响应的View,找到之后通过pointInside:来判断当前的点在那个subview里面,并决定是否响应.

3.遍历子视图,是倒序遍历 ,也就是最后被添加的视图,会最先被遍历.在每一个视图中都回去调用它的hitTest:withEvent:方法,可以理解为是一个递归调用

4.最后看hitTest是否返回vIEW 如果有那就响应事件,并结束当前的事件传递.

事件响应流程

1.如果view 的控制器存在,就传递给控制器处理,如果控制器不存在,就传给他的父视图.

2.在视图结构的最顶层,如果也不能处理收到的事件,那就传给uiwindow.

3.如果uiwindow也不能处理,那就给uiapplication.

4.如果application 也不能处理那就,舍弃.

实例场景

指定一个view的指定一个圆形区域响应区域. 例如: UIView *tagertV = [UIView new]; 首先判断当前点击的点,是否在view的里面.

  • -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 获取当前点点击坐标.

  • 通过 -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 来指定响应区域.

参考文章