汇报学习成果时间到。

今天接触的是IOS中事件传递链以及响应链本身。

事不宜迟马上开始把


1.事件的传递、响应链原理

事件产生、传递的核心为:UIResponder 响应对象

在IOS代码中并不是任何对象都能响应对象,必须是继承了UIResponder的对象才能接受以及处理事件。这些对象我们称之为“响应对象”

响应对象有三

1.UIApplication

2.UIView

3.UIViewController

UIResponder本身提供了多个触摸对象方法来回馈响应,touchBegan,touchMove,touchEnd等~


回到话题,那么事件传递是个怎么样的过程呢?

例: Touch --> UIApplication --> windos --> 适合处理的子控件 --> 处理事件 

简要说,是由父控件到子控件的过程。从接触单击屏幕,接触时产生事件,经由队列传递给UIApplication,然后传递到windos,经由windos找到适合处理的子控件处理事件。

首先为什么用队列而不是堆栈传递呢?此处可用到昨天随笔的内容之一。

因为队列具有先进先出(FIOI)的特性,而堆栈恰好相反。先产生的事件先处理,这才是符合常理的。

此时又引出一个新的问题。

什么是 适合处理的子控件 呢?

1.判断当前事件,windows是否能接受并且传递。

2.判定触摸点是否在控件本身上。

3.View的子控件中往后遍历自身子控件,是否能找到数组中最后的控件元素。

4.View中的子控件遍历,直到没有更合适View的为止。

5.如果无合适的控件,那么自身就为最合适View。

其中View不能接受事件的情况有以下三个

1.自身被隐藏,即HIDE = YES;

2.锁定为不可交互,即UserinteractionEnable = NO;

3.透明度低于0.01,即Alpha ≤ 0.01;

这么一讲肯定又有人说了,这都是什么意思?

这时候我们结合图片来讲解一下

iOS 点击事件 传递多个参数 ios 事件传递与视图响应链_iOS 点击事件 传递多个参数

1.点击绿色控件

Touch - > UIApplication - > windos - > 白 - > 红 - > 绿 - > 处理

当点击绿色控件时,Touch事件经队列传递到UIApplication,此时判定windos中是否不能接受事件,能接受将事件传递到白色控件,此时白色控件接着进行判定:自身是否不能接受事件、触碰点是否在自身身上。并且遍历自身子控件(红色控件、绿色控件)进行同样的判定操作,直到找到合适的控件(绿色控件)为止。

点击灰色控件也是同理以下就不具体阐述了。

回到问题本身,合适控件到底是怎么个定义呢?什么才是合适的呢?

此处引入俩个重要的方法

1.hitTest: WithEvent:

作用:找到并返回 最适合view 的结果 。

当事件传递到控件本身,控件自身会调用hitTest: WithEvent:方法,不管触摸点在不在自身身上,本身适不适合。都会优先调用。不管事件传递给谁,都会调用其本身的hitTest: WithEvent:方法。直至找到最适合View为止。

* 重写hitTest: WithEvent:方法可以拦截事件的自动传递链,能将事件传递重写方法的控件对象本身。

引入该方法后那么传递时间的顺序就变成

真·传递事件顺序:产生触摸事件 - > 通过队列方式将事件传递至UIApplication - >将事件传递到windos时,调用 [UIWindos hitTest: withEvent] - >返回更适合View结果后再继续进行判断 - > 遍历子控件,各自执行["子控件" hitTest: withEvent] - > 直至找到最合适View返回结果。

 

2.pointInside;

作用:判定点是否在当前View上。

如果判定返回YES,代表判定点在当前View上并执行上述操作。如果判定返回NO,则方法调用者本身不能接收以及处理事件。


那么事件响应本身又是怎么样的呢?

响应链本身实际上就是传递链的倒叙。是由多个响应对象链接起来的链条。

通俗易懂的意思就是怎么进去就怎么出来

以下用俩幅图作为表示俩种响应链的关系

iOS 点击事件 传递多个参数 ios 事件传递与视图响应链_iOS 点击事件 传递多个参数_02

iOS 点击事件 传递多个参数 ios 事件传递与视图响应链_iOS 点击事件 传递多个参数_03

响应者对象:能处理事件的对象,也是继承了UIResponder的对象。

作用:可以看清楚每个响应者之间的关系,也可以将一个事件让多个响应者对象处理。

如何判定上一层响应者:

1.如图1,在当前View以及其子控件为该当前ViewController的子控件时,其上级响应者就是ViewController

2.如图2,当当前View的父控件不是当前窗口的ViewController时,其上级响应者为其父控件

对应图1的响应链简述

1.当事件传递给子控件 Initlal View时,判断自身能否处理。不能处理事件时,将事件传递给父级 View

2.父级View 继续判断自身能否处理事件,不能处理事件时,传递给 上级父级View

3.当自身View控件不能处理事件时,交由ViewController判断事件能否处理。如果ViewController不能处理则向高级响应对象Windos传递

4.当Windos都无法处理该事件时,则继续向最上层UIApplication传递事件。

5.当UIApplication无法处理该事件时,该事件将被弃置


将事件传递和响应的概念理解的差不多时,总结一下吧

事件传递与响应俩者融合在一起是什么样的一个处理情况呢?

1.当第一个事件发生后

Touch -  > UIApplication - > WIndos - > UIView - > Initlal View

2.对应事件的响应

Initlal View - 判断是否能处理 > NO - >  传递至SuperView

superView - 判断是否能处理 > NO - >  传递至ViewController

ViewController - 判断是否能处理 > NO - > 传递至Windos

Windos - 判断是否能处理 > NO - > 传递至Application

Application - 判断是否能处理 > NO - > 事件处理失败,废弃

以上判断为YES时,事件处理成功流程结束。

3.特殊情况

1.当某个控件实现了touches..方法时,则事件传递至该控件由该控件处理。

2.当某个控件实现了superTouches..方法时,则事件传递至该控件后继续顺延着响应对象链往上传递

 

最后总结俩句话:

事件的传递是至上而下(父控件 - > 子控件)

事件的响应是至下而上(子控件 - > 父控件)*顺应着响应对象链向上传递

END