响应者链

按照时间顺序,事件的生命周期是这样的:
  事件的产生和传递

  • 事件如何从父控件传递到子控件并寻找到最合适的view、寻找最合适的view的底层实现、拦截事件的处理)->找到最合适的view后事件的处理(touches方法的重写,也就是事件的响应)

事件的传递

触摸事件的传递是从父控件传递到子控件,
也就是UIApplication->window->寻找处理事件最合适的view

注 意:如果父控件不能接受触摸事件,那么子控件就不可能接收到触摸事件

**详述: **
UIEvent对象

    1. 发生触摸事件后,系统检测到手指触摸(Touch)操作时会将其打包成一个UIEvent对象, 并且将该事件加入到一个由UIApplication管理的事件队列中
    1. UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发送事件给应用程序的主窗口(keyWindow)。
    1. 主窗口接收到应用程序传递过来的事件后,首先判断自己能否接受触摸事件。如果能,那么在判断触摸点在不在窗口自己身上
    1. 如果触摸点也在窗口身上,那么窗口会从后往前遍历自己的子控件(遍历自己的子控件只是为了寻找出来最合适的view)
    1. 遍历到每一个子控件后,又会重复上面的两个步骤(传递事件给子控件,1.判断子控件能否接受事件,2.点在不在子控件上)
    1. 如此循环遍历子控件,直到找到最合适的view,如果没有更合适的子控件,那么自己就成为最合适的view。
    1. 找到最合适的view后,就会调用该view的touches方法处理具体的事件。

事件的响应

事件响应是从子控件到父控件。

最合适的view会调用自己的touches方法处理事件, 如果没有实现默认会将事件传递给上一个响应者 , touches默认做法是把事件顺着响应者链条向上抛。

注意:touches的默认做法:只要点击控件,就会调用touchBegin: withEvent:,如果没有重写这个方法,自己处理不了触摸事件

详述:

    1. 首先看initial view能否处理这个事件,如果不能则会将事件传递给其上级视图(inital view的superView);
    1. 如果上级视图仍然无法处理则会继续往上传递;
    1. 一直传递到视图控制器view controller,首先判断视图控制器的根视图view是否能处理此事件;
    1. 如果不能则接着判断该视图控制器能否处理此事件,如果还是不能则继续向上传递;(对于第二个图视图控制器本身还在另一个视图控制器中,则继续交给父视图控制器的根视图,如果根视图不能处理则交给父视图控制器处理);
    1. 一直到 window,如果window还是不能处理此事件则继续交给application处理,如果最后application还是不能处理此事件则将其丢弃

重点: 在事件的响应中,如果某个控件实现了touches...方法,则这个事件将由该控件来接受,如果调用了[super touches….];就会将事件顺着响应者链条往上传递,传递给上一个响应者;接着就会调用上一个响应者的touches….方法

如何判断上一个响应者

  • 如果当前这个view是控制器的view,那么控制器就是上一个响应者
  • 如果当前这个view不是控制器的view,那么父控件就是上一个响应者

响应者链条有什么用
可以让一个触摸事件发声的时候让多个响应者同时响应该事件
在子类的实现文件里的touchesBegan:方法里加上如下代码即可
[super touchesBegan:touches withEvent:event]

如何做到一个事件多个对象处理:
因为系统默认做法是把事件上抛给父控件,所以可以通过重写自己的touches方法和父控件的touches方法来达到一个事件多个对象处理的目的。

你可能感兴趣的:(响应者链)