事件处理标签主要用于了解iOS 中用户和 UI界面交互是靠怎样的机制完成的。
UIResonder
- 只有继承了
UIResonder
的对象才可以接受并处理事件,这些对象被称为响应者对象。 UIApplication
、UIViewController
、UIView
都继承自UIResponder,因此它们都是响应者对象,都能够接收并处理事件
UIResponder内部提供了以下方法来处理事件:
触摸事件
1 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; |
对于触摸事件,如果想要支持多手指触摸,需要设置一个属性:
上述相应触摸事件的 touches 是一个有UITouch
对象的集合。关于 UITouch 的知识请点击UITouch
UIEvent常见属性
- 事件类型
1
2@property(nonatomic,readonly) UIEventType type;
@property(nonatomic,readonly) UIEventSubtype subtype; - 事件产生的时间
1
@property(nonatomic,readonly) NSTimeInterval timestamp;
加速计事件
1 | - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event; |
远程控制事件
1 | - (void)remoteControlReceivedWithEvent:(UIEvent *)event; |
事件的传递和传递原理
第一步:
当发生触摸事件后,系统将会将该事件加入到一个由 UIApplication 管理的事件队列中,UIApplication 会从事件队列中取出最前面的事件,发送下去以便处理,通常发送事件给应用程序的主窗口(keyWindow),主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件。第二步:
找到最合适的视图控件后,会调用视图控件的 上述处理事件方法 方法。
示例:
点击了绿色view:
UIApplication -> UIWindow -> 白色 -> 绿色
点击了蓝色的view:
UIApplication -> UIWindow -> 白色 -> 橙色 -> 蓝色
点击了黄色view:
UIApplication -> UIWindow -> 白色 ->橙色 -> 蓝色 ->黄色
如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸事件
一个视图无法接受触摸事件可能是以下三种情况:
- 不接收用户交互
- userInteractionEnabled = NO
- 隐藏
- hidden = YES
- 透明
- alpha = 0.0 ~ 0.01
其中:UIImageView 的 userInteractionEnable 默认时 NO,因此 UIImageView 以及它的子控件默认时不能接受触摸事件的。
事件如何从父控件传递给子控件?(窗口如何找到最合适的视图)
- 首先,判断自己是否能接受触摸事件?
- 然后判断触摸点是不是在自己身上?
- 从外往里遍历子控件,重复前面的两个步骤
当一个视图接受到事件传递时,就会调用 -hitText
方法,这个方法用于判断找出最合适的 view,找到最合适的 view 后就会调用相应的处理方法。
具体代码如下:
1 | - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event |
hitText小练习1
核心代码:
1 |
|
练习2
触摸事件的处理(响应者链条)
当事件传递到最合适的 view 上时,系统的默认做法时交给父类去处理。[super touch]
,将事件顺着响应者链条向上处理,将事件交给上一个响应者处理。
作用:搞清楚响应者链条,可以让一个事件,多个对象处理。响应者对象:继承了UIResonder
的可以处理事件的对象。
注意:如果当前 view 是控制器的 view,那么控制器就是上一个响应者。因为控制器也可以处理事件,继承UIResonder
,如果当前 view 不是控制器 view,则父控件是上一个响应者。