汇报学习成果时间到。
今天接触的是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;
这么一讲肯定又有人说了,这都是什么意思?
这时候我们结合图片来讲解一下
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,则方法调用者本身不能接收以及处理事件。
那么事件响应本身又是怎么样的呢?
响应链本身实际上就是传递链的倒叙。是由多个响应对象链接起来的链条。
通俗易懂的意思就是怎么进去就怎么出来
以下用俩幅图作为表示俩种响应链的关系
响应者对象:能处理事件的对象,也是继承了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