事件传递和响应者链条

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ldszw/article/details/52051994

iOS中的事件


首先iOS中的事件分为三种:

  • 触摸事件
  • 加速计事件
  • 远程控制事件

那么这篇文章主要讲解就是触摸事件!

事件的产生和传递


传递过程如下:

  • 发生触摸事件后,系统会将该时间加入到一个由UIApplication管理的事件队列中

  • UIApplication会从事件队列中取出最前面的事件,然后将事件分发下去以便处理,通常,先发送事件给应用程序的主窗口(keywindow)

  • 主窗口会在视图层次结构中找到一个最适合处理事件的视图来处理

  • 找到合适的视图控件后,就会调用视图控件的touchs方法来做具体的事件处理

    • touchesBegan…
    • touchesMoved…
    • touchesEnded..

举例说明:

这里写图片描述

在上图中,如果我们点击了绿色View,那么事件的传递就是:
UIApplication -> UIWindow -> 白色View -> 绿色View

所以这就引出一个结论:如果父控件不能接受触摸事件,那么子控件就不可能接受到触摸事件

如何找到最适合的控件来处理事件呢?


这个解决方案是遵循一套原则的:

  • 自己是否能接受到触摸事件?
  • 触摸点是否在自己身上?
  • 从后往前遍历子控件,重复上面两个步骤(递归)
  • 如果没有适合的子控件,那么就自己最适合处理

该原则就是hitTest方法的底层实现原理,同时 hitTest内部也是通过调用pointInside方法去判断触摸点在不在自己身上


举例说明:

按照上图所示,假如视图添加顺序是: 白色View中先添加绿色View,再橙色View,橙色View中先添加蓝色View, 再红色View,蓝色View中有黄色View

事件处理详细流程:这时我们点击了橙色View,那么首先UIWindow会接受事件(上面两条满足), 然后找到子控件白色View(也满足), 接着找到子控件橙色View(该View是后添加的,也满足),所以找到子控件红色View(后添加的,触摸点不在自己身上,不满足),接着找到子控件蓝色View(触摸点不在自己身上,不满足),由于橙色View的子控件都不满足以上条件,所以就自己处理该事件


视图不接受触摸事件的三种情况

  • userInteractionEnabled = NO, 不接受用户交互

  • hidden = YES, 隐藏

  • alpha = 0.0~0.01, 透明

提示:UIImageView默认userInteractionEnabled就为NO,所以UIImageView以及它的子控件默认是不能接受触摸事件的

触摸事件处理的详细过程


  • 用户点击屏幕后产生一个触摸事件,经过一系列的传递后,会找到最合适的视图控件来处理该触摸事件

  • 找到最合适的视图控件来处理该触摸事件后,就会调用视图控件的touches方法来做具体的事件处理

  • 这些touches方法默认做法是将事件按照响应者链条向上传递,将事件交给上一个响应者对象处理(也就是判断当前响应者是否实现touches方法,没有实现默认会把事件传递给上一个响应者)

那么又引申出另外一个概念:何为响应者, 何为响应者链条?

响应者对象,响应者链条


在iOS中不是任何对象都可以处理事件,只有继承自UIResponder的对象才能接受并处理事件,我们称之为“响应者对象

响应者链条如下图所示:
这里写图片描述

很多响应者链接在一起组合起来的一个链条称为响应者链条!

那么如何判断当前响应者的上一个响应者对象是谁呢?

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

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

在视图层次结构中的最顶级视图,如果也不能处理接受到的事件或消息,那么就会将事件或消息传递给window对象处理,如果window对象也不能处理,则将事件或消息传递给UIApplication对象,如果UIApplication对象也不能处理该事件或消息,则将其丢弃!

响应者链条有何作用呢?

可以让一个触摸事件发生的时候让多个响应者同时响应!

猜你喜欢

转载自blog.csdn.net/ldszw/article/details/52051994
今日推荐