美文网首页
初探iOS事件机制

初探iOS事件机制

作者: 三十一_iOS | 来源:发表于2017-03-02 16:09 被阅读60次

    什么是响应链

    响应链是一堆可以处理事件的对象构成的具有先后循序的链条。
    iOS 中有一个类叫做 UIResponder ,它的头文件如下图:

    14884344488032.jpg

    UIResponder 是可以响应事件的的类的基类,只有继承自 UIResponder的类才可以响应用户的操作。包括最常见的 UIViewUIWindowUIViewController等。

    在我们的app中,所有的视图都是按照一定的结构组织起来的,即树状层次结构,每一个View 都有自己的superView。当一个View被添加到superView上时,View的nextResponder就被指向superView,UIViewController 的self.view 被添加到superView上时,self.view 的 nextResponder 指向UIViewControllerUIViewControllernextResponder 指向superView。这样整个app 就通过 nextResponder 形成了一条链,也就是我们说的响应链。

    如何确认第一个响应者

    响应链建立后,当用户点击屏幕时,如何确认第一个响应者?

    每当手指接触屏幕,UIApplication接收到手指的事件之后,就会去调用UIWindow的- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;,看看当前点击的点是不是在window内,如果点击的点不在UIWindow内,第一响应者就是UIApplication,如果点击的点在UIApplication内部,则继续依次调用window的subView的- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;方法,查看点击的点是否在当前subView试图内,如果不在则第一响应者就是window,如果在就继续上面的流程,遍历子视图,直到找到最终的视图。最后找到的视图就是第一个响应者。

    其实只是单纯的说点击的点在不在视图内是不准确的,因为- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;方法判断的不只是点范围的问题,具体的还包括视图是否隐藏、视图是否可交互、视图的透明度是否大于0.01等,这些都满足后,才能确认这个视图是否响应事件。下面这张图很清楚的画出了这个流程:

    14884368969345.jpg

    其实还有一种容易疑惑的情景,当两个视图有重叠时,如何确认那个视图响应事件。

    14884375762669.jpg

    当用户点击红色和蓝色重叠的部分时,系统是如何确认红色和蓝色那个视图响应事件呢?

    这就牵扯到subview调用- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event的顺序,调用的顺序是根据subview的index顺序,index越大越先被访问(越后被添加到父视图,index越大)。如果确认是蓝色视图响应事件,红色视图的- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event方法就不会再被调用。

    响应链的工作机制

    当确认了第一个响应者后,事件就被传递到这个响应者处理。
    如果他不出理,就会通过nextResponder传递到下一个响应者处理,知道找到一个响应者处理,或者到了AppDelegate仍未找到响应者处理,事件丢弃。

    可以用来做什么

    最常见的应用就是改变按钮的点击相应区域。
    一个好用的UIButton扩展


    参考链接

    事件传递响应链

    深入浅出iOS事件机制
    iOS Events and Responder Chain

    相关文章

      网友评论

          本文标题:初探iOS事件机制

          本文链接:https://www.haomeiwen.com/subject/bbhkgttx.html