iOS上的事件传递:第1部分

如果您的iOS应用程序可以处理轻击,滑动,平移或任何其他外部交互,则它使用的是幕后事件。 这些事件采用的路径是一个定义明确的过程,我们将研究它的工作方式。 当调试一些棘手的问题(涉及文本输入或远程控制事件)时,了解此过程的工作原理很方便。 您甚至可以使用此知识使自定义数据流通过您的应用程序。

这是有关事件传递的系列文章中的第一篇。 它将涵盖触摸处理,如何将简单的触摸转变为通过应用程序传递的事件以及如何为组件提供处理该事件的机会。

触摸处理

触摸事件是iOS应用程序处理的事件的主要形式。 我们每天使用的API隐藏了许多如何处理触摸的细节。 了解如何在应用程序中传递这些事件可以帮助确定应用程序的构建方式。 您甚至可以使用此基础结构传递自定义事件。

命中测试

在讨论事件传递时,要讨论的第一件事是系统如何处理触摸事件以及这些事件通过应用程序的路径。 一旦用户点击屏幕,事件就会开始。 在适当的组件可以处理触摸之前,系统需要确定在何处发生触摸以及谁在响应该触摸时首先遇到裂缝。

这是命中测试起作用的地方。

命中测试过程中涉及的方法是hitTest:withEvent:pointInside:withEvent:。 hitTest:withEvent:使用pointInside:withEvent:来确定要命中的测试点是否在其范围内。 如果不在边界内,则返回nil并跳过视图层次结构的整个分支。

如果测试点在范围内,则在每个子视图上调用pointInside:withEvent:。 对于从pointInside:withEvent:返回YES的子视图,将调用hitTest:withEvent:。 原始hitTest:withEvent:调用的最终结果是子视图之一或self的结果(如果其所有子视图均返回nil)。

采取以下视图层次结构:

假设用户在View E中轻按。该过程从View A中的hitTest:withEvent:开始pointInside:withEvent:对于视图A返回YES ,因此在视图B和视图C上调用pointInside:withEvent:。视图B返回NO 。 视图C返回YES,因此将其调用hitTest:withEvent:。 视图C与视图D和视图E遵循相同的过程。视图D在pointInside:withEvent:上返回NO 。 视图E返回YES ,然后在hitTest:withEvent:上返回自身,因为它没有任何子视图。

假设视图D是视图C的子视图,那么如果用户在视图D超出视图C的范围内点击,会发生什么? (当clipsToBoundsNO时,可能会发生这种情况。)视图A启动上述过程。 视图B和视图C的pointInside:withEvent:均返回NO ,因此视图A最终获得了触摸。

现在,我们有了hitTest:withEvent:的视图。 该视图称为“命中测试”视图。 现在,它与触摸相关联,在触摸处于活动状态时,将获得第一个机会以响应任何触摸事件(稍后会详细介绍)。

如果没有针对给定触摸的自定义实现,会发生什么? 这取决于。 如果视图是由视图控制器管理的,则视图控制器将有机会做出响应。 如果该视图控制器没有响应,则为命中测试视图的超级视图提供响应的机会。 一直重复此过程,直到称为“响应者链”为止。

响应者链

响应者链是责任链设计模式的一种实现。 响应者链中的每个参与者都继承自UIResponder。 UIResponder包含处理各种类型事件的离散方法。 除了触摸事件外,UIResponder还声明用于处理输入视图,运动事件,按下事件和远程控制事件的方法。

对于许多此类事件, firstResponder很重要。 firstResponder是第一个获得处理事件机会的对象。 如果第一个响应者不处理事件,则它的nextResponder有机会处理事件,并且重复该过程,直到当前对象上的nextResponder为零。 链中的最后一个对象通常是应用程序委托。

手势

在iOS中,手势识别器应运而生,触摸处理过程就是应用程序检测和处理手势的方式。 引入UIGestureRecognizer后,该过程将稍作更改,以使手势能够处理触摸并根据其检测到的手势执行操作。 我们将不讨论如何使用手势识别器。 相反,我们将研究手势如何适合触摸事件传递系统。

手势始终是第一个处理触摸事件的机会。 默认情况下,手势首先获取触摸,然后获取视图。 主要区别在于,当手势的状态被“识别”时,视图上的触摸被取消。 您可以通过使用UIGestureRecognizer:cancelsTouchesInViewdelaysTouchesBegandelaysTouchesEnded上的这些属性来控制如何将这些触摸事件传递给视图。 明智地使用这些属性,因为它们可能会导致无响应视图的错觉。

包起来

在第一部分中,我们为触摸事件如何从窗口传播到通过响应者链沿相似路径被触摸的视图奠定了基础。 我们还介绍了手势识别器如何适合此触摸系统。 在第2部分中,我们将讨论受支持的其他事件以及响应者链适合的位置。