理解事件处理,响应者和响应者链

移动开发 简书

原文地址:

如原作者发现有侵权行为可责令我在24小时之内删除,前提是你能看到。

翻译者:毛毛可

学习事件是怎样在你的app中传递的,并学会应该如何处理它们.

Apps使用responder(响应者对象)对象来接受并处理事件.一个responder对象可以是任意一个UIResponder类的实例,其中包括其子类UIView,UIViewController和UIApplication.

responder对象在接收到原始的事件对象,必须处理它或者将它继续向前传递给下一个responder对象.当你的app在接收到一个事件时,UIKit框架会自动的找到最合适的responder去处理该事件,这就是第一响应者.

未处理的事件会在响应者链中从这个responder传递给下一个responder.事实上你的app中没有单独的响应者链.UIkit定义了responder传递的默认规则,当然你可以通过覆盖responder对象中对应的属性来更改规则.

图一

图一

显示了一条默认的响应者链,包括一个label,一个text field,一个button和两个background view.如果text field不去处理事件,那么UIKit会将事件发送给textfield的父视图对象.接着就是window的root view.从root view出来,会顺着响应者链在到达window对象之前先传递给view controller.如果此时window也不处理此事件,UIKit会将事件分发给UIApplication对象,或者是分发给app delegate,app delegate是一个UIResponder实例,但此过程已经不是响应者链中的一部分了.

确定事件的第一响应者

针对每种类型的事件,UIKit指定了第一响应者,将事件发送给第一响应者.第一响应者的确定是基于事件的类型的.

Touch事件

第一响应者就是触摸发生的view.

Press事件

第一响应者是注册了focus的响应者对象.

摇动事件

第一响应者是你指定的相应对象.

远程控制事件

第一响应者是你指定的相应对象.

编辑菜单信息

第一响应者是你指定的相应对象.

Note

运动事件相关的加速,陀螺仪和磁力计都不会出现在响应者链中.Core MOtion会派发这些事件给你对应注册的对象.

UIControl控件会直接通过相关联的target-action传送事件.

当界面中的是UIControl控件时,UIControl会调用target对象的action方法,或者说返送一个action消息给其target对象.

action消息不是一个事件,但是依然可以利用响应者链.当UIControl对象的target为nil时,UIKit开始从target对象并顺着响应者链找,直到找到一个实现了相关action方法的对象.举例,UIKit editing menu使用这种行为去搜索对应responder对象的相关实现方法比如 cut: , copy: 或者 paste: .

如果在view中有附加的手势识别器,手势识别器会在在view之前接收到touch和press事件.如果view中所有的手势识别都没有识别成功,事件会传给view去处理.如果此view没有处理它们,UIKit会继续传给响应者链的上一层.关于更多的手势识别器处理事件,请参考UIKit Gestures.

确定哪个Responder包含Touch事件

UIKit使用 基于view的hit-testing方式去确定touch事件发生的位置.具体来说,UIKit会将touch的位置与在view层级中的view对象的容器范围比较.UIView的 hitTest:withEvent: 方法随着view层级,查找包含touch的最深层的子view.这个view将成为touch事件的第一响应者.

Note

如果touch的位置超出了view的范围, hitTest:withEvent: 方法会忽略此view及其所有子view.因此,当view的clipsToBounds属性为NO时,即使包含了touch,超出view范围的子view也不会有效.更多关于 hitTest:withEvent: 方法的行为,请查看view的 hitTest:withEvent: 方法.

UIkit总会赋值给view其范围范围的每个touch.当触摸发生时,UIKit创建UITouch对象,直到触摸结束后才释放touch对象.如果触摸的位置或者其他参数改变了,UIKit会及时更新UITouch对象的信息.只有一个属性不可能发生改变就是是否在view范围中.及时当触摸位置移出了原view,touch对象的属性也不会改变.

改变响应者链

你可以通过重载responder对象的nextResponder属性来改变响应者链.你可以在此方法(getter)返回下一个响应者.

许多UIKit的类已经重载了这个属性,返回了指定的对象.

UIView对象,如果view是view controll的根视图,那么view的下个响应者就是view controller,否者下一个响应者就是view的父视图.

UIViewController对象.

如果一个vc是被另一个vcpresent出来的,那么vc的下一个响应者就是present它出来的那个vc

如果window的根视图是view controller.view,那么view controller的下一个响应者就是window对象.

window对象.window的下一个responder是UIApplication对象.

UIApplication对象.下一个响应者是app delegate.

简书稿源:简书 (源链) | 关于 | 阅读提示

本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 移动开发 » 理解事件处理,响应者和响应者链

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录