一.事件响应者链
事件传递和事件响应链
区别
事件的传递和响应的区别:
事件的传递是从上到下(父控件到子控件),事件的响应是从下到上(顺着响应者链条向上传递:子控件到父控件。
引出
当我们手指触摸屏幕的时候,iOS系统是怎么找到对应的图层,并响应手势的呢?
事件的产生
- 发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中,为什么是队列而不是栈?因为队列的特点是先进先出,先产生的事件先处理才符合常理,所以把事件添加到队列。
- UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发送事件给应用程序的主窗口(keyWindow)。
- 主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件,这也是整个事件处理过程的第一步。
找到合适的视图控件后,就会调用视图控件的touches方法来作具体的事件处理。
事件的传递
从下往上
- 触摸事件的传递是从父控件传递到子控件
- 也就是UIApplication->window->寻找处理事件最合适的view
首先,对于图层结构来说无非是window上一层一层的View图层,当我们触摸window上的某一个图层的时候,这个时候会从最下面也就是window 上开始递归遍历上边的图层,当找到上层的某一个view图层之后,会继续在此view内再次重复以上操作,直到找到手指触摸的view,响应事件。
事件响应 查找顺序 从后往前遍历子视图
先从子控件数组中最后一个元素,依次查找目标的view,如果没有合适的处理这个事件的view那么此view就是合适的view,去响应事件
当然 有三种情况 不能接收触摸事件
- 不允许交互:userInteractionEnabled = NO
- 隐藏:如果把父控件隐藏,那么子控件也会隐藏,隐藏的控件不能接受事件
- 透明度:如果设置一个控件的透明度<0.01,会直接影响子控件的透明度。alpha:0.0~0.01为透明。
两个方法
- hitTest:withEvent:方法 当事件传递一个控件给另外一个控件的时候调用,这个方法如果重写了,那么返回的view就是合适的view,如果没有返回view,那么调用这个事件的控件本身和其子控件都不是合适的view,那么此时最合适的view就是它的父view。
- pointInside方法 在底层会判断点是否在此view的坐标系上。由 hitTest:withEvent:调用时候触发。