什么是事件传递
事件传递:在iOS系统中,事件可以分为三类:
public enum EventType : Int {
case touches // 触摸事件
case motion // 运动事件(比如重力感应、摇一摇等等)
case remoteControl // 远程控制事件(比如可以用耳机控制手机)
@available(iOS 9.0, *)
case presses
}
touch events 大多数都是相同的,并且在触摸事件发生的时候会传递给view;
motion events 由UIKit触发,并且会由Core Motion framework区分motion events;
Rmote-control events 允许响应对象接收来自 external accessory 或者 headset 的命令,这样就可以管理音频和视频了;
Press events 表示 a game controller 和 AppleTV 或者 其他有物理按键的设备的远程事件之间的交互
事件的传递过程:主要针对的是touch events
当我们触摸屏幕的时候,为我们找到最合适的view。
每当手机触摸屏幕,操作系统会把事件传递给当前的APP,在UIApplication接收到手指的事件之后,就会去调用 UIWindow 的 hitTest:withEvent: 方法,看看当前点击的点是不是在window内,如果是则继续调用其subview的 hitTest:withEvent: 方法,直到找到最后需要的view。
hitTest:withEvent: 的内部实现
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if (self.hidden || self.userInteractionEnabled == NO || self.alpha < 0.01 || [self pointInside:point withEvent:event]) {
return nil;
}
for (UIView *subView in self.subviews.reverseObjectEnumerator) {
UIView *hitView = [subView hitTest:[subView convertPoint:point fromView:self] withEvent:event];
if (hitView) {
return hitView;
}
}
return self;
}
什么是响应过程
在事件传递过程中,找到事件响应的view,控件调用 touch 的一系列方法,判断是否实现 touch 的一系列方法,如果没有实现,就将事件传递给上一个响应者,如果最终找不到,方法作废
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
如果有实现就由此View来响应,如果没有实现,那么就传递给他的下一个响应者。
我的理解:
在开发中的应用
1.拦截点击事件
重写父视图的 hitTest:withEvent: 方法
2.扩大点击面积
// 方法一
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
CGRect rect = self.bounds;
rect = CGRectInset(rect, -30, -30); // 增加点击面积
return CGRectContainsPoint(rect, point);
}
// 方法二
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
CGRect rect = self.bounds;
rect = CGRectInset(rect, -30, -30); // 增加点击面积
if (CGRectContainsPoint(rect, point)) {
return self;
}
return nil;
}
网友评论