iOS Responder Chain

来源:互联网 发布:linux 除法 保留小数 编辑:程序博客网 时间:2024/06/05 10:41

一. UIResponder类

UIApplicationUIViewController,UIView和所有继承自UIView的UIKit类(包括UIWindow,继承自UIView)都直接或间接的继承自UIResponder,所以它们的实例都是responder object对象。


二.响应链

响应链简单来说,就是一系列的相互关联的对象,从firstResponder开始,到application对象结束,如果firstResponder 无法响应事件,则交给nextResponder来处理,直到结束为止。

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


三  nextResponder

1、UIView的nextResponder是直接管理它的UIViewController(也就是VC.view.nextResponder=VC),如果当前View不是ViewController直接管理的View,则nextResponder是它的superView(view.nextResponder = view.superView)

2、UIViewController的nextResponder是它直接管理的View的superView(VC.nextResponder = VC.view.superView)

3、UIWindow的nextResponder是UIApplication

4、UIApplication的nextResponder是UIApplicationDelegate(官方文档说是nil)

四  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


五  Touches Events 理解


我们在重写TouchesEvents的时候,如果不想让响应链继续传递,就不调用super对应的实现就可以了,但是你不想中断响应链,你就需要调用父类对应的实现。调用super的目的就是为了把事件传递给nextResponder,并且如果我们在 touchesBegan 中没有调用super,则super不会响应其他的回掉(touchesMoved/touchesEnded),但是我们需要重写所有如上所示的方法来确保我们的一切正常。touchesBegan 和 touchesEnded/touchesCancelled一定是成对出现的,这点大家可以放心。


六 杂谈

响应链能够处理很多东西,不仅仅是触摸事件。一般来说,如果我们需要一个对象去处理一个非触摸事件(摇一摇,RemoteControlEvents,调用系统的复制、粘贴框等),我们要确保该对象是UIResponder子类,如果我们要接收到事件的话,我们需要做两件事情

1、重写canBecomeFirstResponder ,并且返回YES

2、在需要的时候像该对象发送becomeFirstResponder消息。

如果你自己想自定义一个非TouchEvent的事件,当需要继续传递事件的话,切记不要在实现内直接显示的调用nextResponder的对应方法, 而是直接调用super对应的方法来让这个事件继续分发到响应链。

UIImageView的默认是不接受点击事件的,如果想要实现如上所示效果,需要设置userInteractionEnabled=YES;

CALayer 不是UIResponder的子类,这说明CALayer(NSObject)无法响应事件,这也是UIView和CALayer的重要区别之一。



0 0