Responder Chain简析

一.responder对象

iOS系统中,能够响应并处理事件的对象称之为responder object,UIResponder是所有responder对象的基类,在UIResponder类中定义了处理各种事件,包括触摸事件(Touch Event)、运动事件(Motion Event)和远程控制事件(Remote-Control Events)的编程接口,其中处理触摸事件(Touch Event)的编程接口如下:

– touchesBegan:withEvent:

– touchesMoved:withEvent:

– touchesEnded:withEvent:

– touchesCancelled:withEvent:

这四个方法分别处理触摸开始事件,触摸移动事件,触摸终止事件,以及触摸跟踪取消事件。

UIApplication,UIViewController,UIView和所有继承自UIView的UIKit类(包括UIWindow,继承自UIView)都直接或间接的继承自UIResponder,所以它们的实例都是responder object对象,都实现了上述4个方法。UIResponder中的默认实现是什么都不做,但UIKit中UIResponder的直接子类(UIView,UIViewController…)的默认实现是将事件沿着responder chain继续向上传递到下一个responder,即nextResponder。所以在定制UIView子类的上述事件处理方法时,如果需要将事件传递给next responder,可以直接调用super的对应事件处理方法,super的对应方法将事件传递给next responder,即使用

[super touchesBegan:touches withEvent:event];

不建议直接向nextResponder发送消息,这样可能会漏掉父类对这一事件的其他处理。

[self.nextResponder  touchesBegan:touches withEvent:event];

另外,在定制UIView子类的事件处理方法时,如果其中一个方法没有调用super的对应方法,则其他方法也需要重写,不使用super的方法,否则事件处理流程会很混乱。

注:UIKit框架的类层次结构图见:UIKit Framework Reference

二.responder chain

上文提到了responder chain,responder chain是一系列连接的responder对象,通过responder对象可以将处理事件的责任传递给下一个,更高级的对象,即当前responder对象的nextResponder

iOS中responder chain的结构为:

UIView的nextResponder属性,如果有管理此view的UIViewController对象,则为此UIViewController对象;否则nextResponder即为其superview

UIViewController的nextResponder属性为其管理view的superview.

UIWindow的nextResponder属性为UIApplication对象。

UIApplication的nextResponder属性为nil。

iOS系统在处理事件时,通过UIApplication对象和每个UIWindow对象的sendEvent:方法将事件分发给具体处理此事件的responder对象(对于触摸事件为hit-test view,其他事件为first responder),当具体处理此事件的responder不处理此事件时,可以通过responder chain交给上一级处理。

如果hit-test view或first responder不处理此事件,则将事件传递给其nextResponder处理,若有UIViewController对象则传递给UIViewController,传递给其superView。

如果view的viewController也不处理事件,则viewController将事件传递给其管理view的superView。

视图层级结构的顶级为UIWindow对象,如果window仍不处理此事件,传递给UIApplication.

若UIApplication对象不处理此事件,则事件被丢弃。

三.巧妙利用nextResponder

通过UIViewController的view属性可以访问到其管理的view对象,及此view的所有subviews。但是根据一个view对象,没有直接的方法可以得到管理它的viewController,但我们使用responder chain可以间接的得到,代码如下:

@implementation UIView (ParentController)

-(UIViewController*)parentController{

UIResponder *responder = [self nextResponder];

while (responder) {

if ([responder isKindOfClass:[UIViewController class]]) {

return (UIViewController*)responder;

}

responder = [responder nextResponder];

}

return nil;

}

@end

参考:

Event Handling Guide for iOS – Responder Objects and the Responder Chain

UIResponder Class Reference

A Bit About the Responder Chain

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 在iOS开发中经常会涉及到触摸事件。本想自己总结一下,但是遇到了这篇文章,感觉总结的已经很到位,特此转载。作者:L...
    WQ_UESTC阅读 6,246评论 4 26
  • 一. Hit-Testing 什么是Hit-Testing?对于触摸事件, window首先会尝试将事件交给事件触...
    面糊阅读 1,035评论 0 50
  • 好奇触摸事件是如何从屏幕转移到APP内的?困惑于Cell怎么突然不能点击了?纠结于如何实现这个奇葩响应需求?亦或是...
    Lotheve阅读 59,492评论 51 604
  • 4事件分发机制 iOS中的事件大概分为三种,分别是Milti-Touch Events, Motion Event...
    Kevin_Junbaozi阅读 904评论 0 2
  • 转至(https://www.oschina.net/question/1777276_2132459) 前言 无...
    码农耕阅读 288评论 0 0

友情链接更多精彩内容