第7章已简单介绍过UIResponder和第一响应对象。UIResponder对象可以接收触摸事件,而UIView是典型的UIResponder子类。除了UIView,还有很多其他的UIResponder子类,其中包括UIViewController、UIApplication和UIWindow。UIViewController不是视图对象,既不能触摸也无法显示,为什么也是UIResponder子类?这是因为虽然不能向UIViewController对象直接发送触摸事件,但是该对象能够通过响应对象链接收事件。
UIResponder对象拥有一个名为nextResponder的指针,相关的UIResponder对象可以通过该指针组成一个响应对象链(见图12-5)。当UIView对象属于某个UIViewController对象时,其nextResponder指针就会指向包含该视图的UIViewController对象。当UIView对象不属于任何UIViewController对象时,其nextResponder指针就会指向该视图的父视图。UIViewController对象的nextResponder通常会指向其视图的父视图。最顶层的父视图是UIWindow对象,而UIWindow对象的nextResponder指向的是UIApplication单例。
图12-5 响应对象链
如果UIResponder对象没有处理传给它的事件,会发生什么?该对象会将未处理的消息转发给自己的nextResponder。这也是touchesBegan:withEvent:这类方法的默认实现。因此,如果没有为某个UIResponder对象覆盖特定的事件处理方法,那么该对象的nextResponder会尝试处理相应的触摸事件。最终,该事件会传递给UIApplication(响应对象链的最后一个对象),如果UIApplication也无法对其处理,系统就会丢弃该事件。
除了由UIResponder对象向nextResponder转发消息,也可以直接向nextResponder发送消息。假设有一个正在跟踪触摸事件的视图,当该视图发生连按事件时,需要由该视图的nextResponder来处理这个事件。相应的代码如下:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if (touch.tapCount == 2) {
[[self nextResponder] touchesBegan:touches withEvent:event];
return;
}
……继续处理非连按触摸事件
}