之前去腾讯面试被问到事件响应机制相关的问题,那个时候还是什么都不懂得,去这种大公司面试一般都是抱着学习的态度取得,当然侥幸的心里还是有的,总会想着万一能行呢。结果吗。。。最起码学习到了很多东西,这波不亏。
iOS的事件响应必须是UIResponder的类及其子类,我们Command查看层级关系不难发现,UITextView,UILabel,UIButton等控件他们的基类都是UIResponder。这也是他们能够响应事件的基础。
我们需要了解下事件分发传递的流程 First Responser -- > The Window -- >The Application -- > App Delegate
- 触摸屏幕,系统生成event对象并将event加入到UIApplication管理的一个任务队列中
- 系统会遍历当前视图及子视图寻找最合适的响应者来执行event,那么系统如何能找到最合适的响应者成为了最关键的地方,他是怎么找到的,又是通过什么样的方法什么样的逻辑找到的呢,下面说一下具体的流程
-
方法:hitTest 和 pointInside 方法
-
逻辑: 递归判断
- 手势触摸,系统会判断触摸点是否在当前视图上
- 如果在,执行hitTest方法。同级子视图遍历规则遵循filo(先进后出)原则
- 找到了这个view 然后执行event,从上往下一次执行,看是否能够执行,不能够执行,找他的同级视图或父视图
-
三种情况下是不会响应事件
- userInteractionEnabled = NO
- hidden = YES
- alpha < 0.01
实用案例,利用hitTest方法修改button按钮点击范围,点击范围扩大2倍
//重写button的hitTest方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
NSLog(@"====%@",NSStringFromCGPoint(point));
CGRect rect = self.bounds;
CGRect newRect = CGRectMake(-rect.size.width/2, -rect.size.height/2, rect.size.width*2, rect.size.height*2);
if (CGRectContainsPoint(newRect, point)) {
return self;
}
return nil;
}
网友评论