前言:面试
不知不觉开发iOS三年之多了,成功的从一个小菜鸟变成了大菜鸟,前些日子面试被问到: iOS中事件传递是怎么样的,touch事件苹果是如何收集的? 因为以前没有了解过这些原理以及实现.一直本着能用就行.遇到这种问题直接懵逼了.
微信
后来经过阅读相关文章简单总结了一下,但愿能够帮助到更多同窗!!!但愿共同成长ide
在iOS中凡是继承自UIResponder的对象都可以接收并处理事件spa
•先说如何会产生touch事件对象
1.触摸事件(例如点击,滑动,缩放等)blog
2.加速计事件(例如摇微信一摇,指南针等)继承
3.远程控制事件(例如蓝牙,wifi)递归
1.触摸事件:队列
当手指触摸手机屏幕时,系统会调用view的事件
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event方法
当手指在手机屏幕上移动时,系统会调用view的
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event方法
当手指离开手机屏幕时,系统会调用view的
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event方法
每一个方法中的touches参数是NSSet类型(也就是集合类型),里边存放的是一个或多个UITouch对象,当手指触摸到屏幕时候会建立UITouch对象(一个手指对应一个UITouch对象),每一个UITouch对象中存放的是这个动做的相关信息(触摸次数,视图大小,位置,类型等相关信息)
当手指离开屏幕后,集合里保存的UITouch对象也会随之销毁.
那咱们来看看这些动做是怎么实现的,首先咱们来看事件是怎么传递的
发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的队列事件中,UIApplication会从事件队列中取出最前边的事件分发下去处理,会先发生给窗口视图KeyWindow
视图会一层一层向上寻找最合适的视图来处理事件.找到合适的视图后会调用该视图的Touch方法(也就是上边说到的touchBegin,touchMove等)去作处理.也就是说该事件传递是从父视图依次向子视图传递的.若是父视图不可以接收并处理事件,那么他的子视图就不能接收并响应事件.
如下几种状况View不能接收并响应事件
1.view.userInteractionEnabled = NO;(不可交互)
2.view.hidden = YES;(隐藏)
3.view.alpha <=0.01;(透明度小于等于0.01)
那么如何找到最合适的视图?
1.本身自己是否能够接收事件
2.触摸点是否在自己范围内
3.查看本身的子控件是否能够接收事件
4.查看触摸到是否在本身的子控件上
5.若是没有就在本身自己处理
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 这个方法就是用来查找最合适处理事件的方法,和-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event配合使用(判断触摸到是否在自身上).
经过上边的步骤.咱们能够本身来模拟一下寻找view的实现
最后总结来讲一次完整的触摸事件的传递响应过程为:
UIApplication-->UIWindow-->递归找到最合适处理的控件-->控件调用touches方法-->判断是否实现touches方法-->没有实现默认会将事件传递给上一个响应者-->找到上一个响应者-->找不到方法做废
最后咱们还可使用响应者链找到当前视图
- (UIViewController *)parentController
{
UIResponder *responder = [self nextResponder];
while (responder) {
if ([responder isKindOfClass:[UIViewController class]]) {
return (UIViewController *)responder;
}
responder = [responder nextResponder];
}
return nil;
}