事件及响应者
响应者: 响应者对象是指能够处理事件的对象,即继承UIResponder的对象
响应者链条:由很多响应者链接组合起来的链条称为响应者链条
iOS中事件用UIEvent类实例出对象来表示,当一个事件发生时会创建一个UIEvent对象,最后将该事件转发给应用程序对象UIApplication。最常见的事件有三种类型:触摸事件,加速计事件以及远程遥控事件。
如下图所示:

UIResponder是所有响应对象的基类,在UIResponder类中定义了处理事件的接口。UIApplication、 UIViewController、 UIWindow 和所有继承自UIView的UIKit类都直接或间接的继承自UIResponder,所以它们的实例都是可以构成响应者链的响应者对象。
响应过程:
一次完整的触摸事件的传递响应的过程
UIAppliction --> UIWiondw -->递归找到最适合处理事件的控件-->控件调用touches方法-->判断是否实现touches方法-->没有实现默认会将事件传递给上一个响应者-->找到上一个响应者
触摸事件的传递:
触摸事件的传递是从父控件传递到子控件,如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸事件,不能接受触摸事件的四种情况, 即:
1.userInteractionEnabled = NO
2.隐藏,即:hidden = YES
3.透明,即:alpha <= 0.01
4.未启用,即:enabled = NO
提示:UIImageView 的userInteractionEnabled默认就是NO,因此 UIImageView 以 及它的子控件默认是不能接收触摸事件的
如何找到最合适处理事件的控件:
发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中。
UIApplication会从事件队列中取出最前面的事件, 并将事件分发下去以便处理,通常先发送事件给应用程序的主窗口。
UIWindow对象会首先在它的内容视图上调用hitTest:withEvent:,这个方法底层会在其视图层级结构中的每个视图上调用pointInside:withEvent:(用来判断点击事件发生的位置是否处于当前视图范围内,以确定用户是不是点击了当前视图),如果pointInside:withEvent:返回YES,则继续逐级调用,直到找到touch操作发生的位置,这个视图也就是要找的hit-test view。
如果当前view是控制器的view, 那么就传递给控制器, 如果控制器不存在, 则将其传递给它的父控件
在视图层次结构的最顶层视图也不能处理接收到的事件或消息,则将事件或消息传递给UIWindow对象进行处理,如果UIWindow对象也不处理,则将事件或消息传递给UIApplication对象,如果UIApplication也不能处理该事件或消息,则将其丢弃( 关于上一相应者:
(1). 如果当前这个 view 是控制器的 view,那么控制器就是上一个响应者
(2). 如果当前这个 view 不是控制器的 view,那么父控件就是上一个响应者
(3). 如果当前响应者是控制器,那么上一个响应者是UIWindow
)

找到响应者后,响应者可以重写以下方法来对事件做响应:
触摸事件:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//让下一个响应者可以有机会继续处理
[super touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[super touchesBegan:touches withEvent:event];
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[super touchesBegan:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[super touchesBegan:touches withEvent:event];
}
加速计事件:
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
-(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
-(void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;
远程控制事件:
- (void)remoteControlReceivedWithEvent:(UIEvent *)event;
网友评论