1.相关概念介绍:
1)iOS 中的事件类型有三种:触摸事件,加速计事件,远程控制事件.
2)响应者对象:只有继承自 UIResponder 类的对象才能接受并处理事件,这些对象成为 响应者对象.
例如: UIApplication UIViewController 以及 UIView 都继承自 UIResponder,都是响应者对象
3) UIResponder 内部提供了方法,处理不同类型的事件
2.处理事件的方法:
处理触摸事件:
1) -(void)touchesBegan: withEvent:
2) -(void)touchesMoved: withEvent:
3) -(void)touchesEnded: withEvent:
4) -(void)touchesCancelled: withEvent:
处理加速计事件:
1) -(void)motionBegan: withEvent:
2) -(void)motionEnded: withEvent:
3) -(void)motionCancelled: withEvent:
远程控制事件:
-(void)remoteControlReceivedWithEvent:
3.触摸事件的传递
1) 发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列
2)UIApplication 单例对象会从事件队列中取出最前面的事件将其分发,最先分发的对象是程序的主窗口
3)主窗口调用 hitTest: withEvent: 方法在视图树中找到一个最合适的子视图来处理触摸事件,该子视图即为 hit-test视图
其中,在寻找处理事件的最合适控件的准则:
1) 判断自己是否能接受触摸事件,如果可以,则继续
2) 判断触摸点是否在自己身上,如果在,则继续
3) 从后往前遍历子控件,重复上面的两个步骤
4) 如果没有符合条件的子控件,那么自己最适合处理
5) 返回找到的最合适处理事件的控件
hitTest: 方法代码演示:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
NSLog(@"%@----hitTest:", [self class]);
// 如果控件不允许与用户交互那么返回 nil
if (self.userInteractionEnabled == NO || self.alpha <= 0.01 || self.hidden == YES) {
return nil;
}
// 如果这个点不在当前控件中那么返回 nil
if (![self pointInside:point withEvent:event]) {
return nil;
}
// 从后向前遍历每一个子控件
for (int i = (int)self.subviews.count - 1; i >= 0; i--) {
// 获取一个子控件
UIView *lastVw = self.subviews[i];
// 把当前触摸点坐标转换为相对于子控件的触摸点坐标
CGPoint subPoint = [self convertPoint:point toView:lastVw];
// 判断是否在子控件中找到了更合适的子控件
UIView *nextVw = [lastVw hitTest:subPoint withEvent:event];
// 如果找到了返回
if (nextVw) {
return nextVw;
}
}
// 如果以上都没有执行 return, 那么返回自己(表示子控件中没有"更合适"的了)
return self;
}
在 上面的方法中,是通过内部调用 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 方法来判断点是否在自己身上的
4.触摸事件的响应
在找到最合适处理触摸事件的控件后,调用控件的 touches方法来作具体的事件处理,后面就是事件响应的传递,具体传递过程可以参考 点我查看 中的事件处理原则部分内容.