iOS - 变乱传递链与相应链

开发者 2024-9-6 05:32:09 32 0 来自 中国
一、变乱链

用户点击屏幕时,起首 UIApplication 对象先收到该点击变乱,再依次传递给它上面的全部子 view,直到传递到最上层。即由体系向最上层 view 传递,Application -> window -> root view -> sub view -> ... -> first view 即传递链。
反之,由最底子的 view 向体系传递,first view -> super view -> ... -> view controller -> window -> Application -> AppDelegate 即相应链。
简朴总结,变乱链包罗传递链和相应链,变乱通过传递链传递上去,通过相应链找到相应的 UIResponse。


二、谁来相应变乱 — 传递链

只有继承了 UIResponser 的对象才可以或许担当处置惩罚变乱。UIResponse 是相应对象的基类,界说了处置惩罚各种变乱的接口。在 UIKit 中我们利用相应者对象 Responder 吸收和处置惩罚变乱。一个相应者对象一样平常是 UIResponder 类的实例,它常见的子类包罗 UIView,UIViewController 和 UIApplication,这意味着险些全部我们一样平常利用的控件都是相应者,如 UIButton,UILabel 等等。
在 UIResponder 及其子类中,我们是通过有关触摸 UITouch 的方法来处置惩罚和传递变乱 UIEvent,详细的方法如下:
open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)open func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?)open func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?)open func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?)UIResponder 还可以处置惩罚 UIPress、加快计、远程控制变乱,这里仅讨论触摸变乱。
在 UITouch 内,存储了大量触摸干系的数据,当手指在屏幕上移动时,所对应的 UITouch 数据也会更新,例如:
这个触摸是在哪个 window 大概哪个 view 内发生的?
当前触摸点的坐标是?
前一个触摸点的坐标是?
当前触摸变乱的状态是?
这些都存储在 UITouch 内里。别的须要注意的是,在这四个方法的参数中,传递的是 UITouch 范例的一个聚集 (而不是一个 UITouch),这对应了两根及以上手指触摸同一个视图的环境。
们以 UIView 来作为视图层级的紧张构成元素,便于明白。但不止 UIView 可以相应变乱,实际只要是 UIResponder 的子类,都可以相应和传递变乱。

2.png
当我们触摸了屏幕。此时所拥有的信息是触摸点的坐标,但无法直接知道用户是想点哪个视图。须要一个战略来找到这个第一相应者,UIKit 为我们提供了掷中测试 hit-testing 来确定触摸变乱的相应者

以下为UIView不担当变乱处置惩罚的环境:
view.hidden = YES;view.userInteractionEnabled = NO;view.alpha < 0.01;详细流程如下:

  • 用户在点击屏幕;
  • 体系将点击变乱加入到 UIApplication 管理的消息队列中;
  • UIApplication 会从消息队列中取出该变乱传递给 UIWindow 对象;
  • 在 UIWindow 中调用方法 hitTest:withEvent: ,在 hitTest:withEvent: 方法中调用 pointInside:withEvent: 来判断当前点击的点是否在 UIWindow 内部;
  • 如若返回 yes,则倒序遍历其子视图找到终极相应的子 view;
  • 如果终极返回一个 view,那么即为终极相应 view 并竣事变乱传递,如果无值返回则将 UIWindow 作为相应者。
此中核心方法如下:
// recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system- (nullable UIView *)hitTestCGPoint)point withEventnullable UIEvent *)event;   // default returns YES if point is in bounds- (BOOL)pointInsideCGPoint)point withEventnullable UIEvent *)event;   

  • 方法 hitTest:withEvent: 用来获取终极相应变乱的 view。
  • 方法 pointInside:withEvent:,用来判断点击的位置是否在视图范围内。
三、怎样传递变乱 —— 相应链

由离用户近来的view向体系传递。如下所示:


图中浅灰色的箭头是指将 UIView 直接添加到 UIWindow 上环境。
相应链应该是:ViewB -> ViewC -> ViewA -> UIViewController 对象 -> UIWindow 对象 -> UIApplication 对象 -> App Delegate
触摸变乱起首将会由第一相应者相应,触发其 (target action) 等方法,根据触摸的方式差别(如拖动,双指),详细的方法和过程也不一样。若第一相应者在这个方法中不处置惩罚这个变乱,则会传递给相应链中的下一个相应者触发该方法处置惩罚,若下一个也不处置惩罚,则以此类推传递下去。若到末了还没有人相应,则会被抛弃(比如一个误触)。
四、完成流程

您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-11-23 20:02, Processed in 0.172073 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表