事件分类
1. 高级事件:控件的点击事件/手势
2. 低级事件:触摸事件
响应流程:
1. 当发生一个触摸事件的时候,系统会把它打包成UIEvent对象,放到由UIApplication管理的一个事件队列里面
2. 等到合适的时机(runloop的运行循环有关),UIApplication会从队头取出一个事件,交给UIWindow对象去处理
3. UIWindow会在视图层级结构中找到最合适的视图让其去处理这个事件
1. window会选中交给离自己最近的视图
2. 调用该视图的-(UIView *)hitTest CGPoint(point) :withEvent(UIEvent *)event方法
* 方法逻辑
1. 判断当前视图是否可以传递事件,以下有任一条件满足进入2,否则返回nil
* 视图.userInteractionEnabled = YES
* 视图.hidden = NO
* 视图.alpha>0.01
2. 判断视图是否在触摸点范围内:通过-(BOOL)pointInSide CGPoint(point) :wihtEvent(UIEvent *)event,返回yes进入3,否则返回nil
3.遍历当前视图的子视图
* 通过:[self convertPoint:point toView:视图.subviews[i]]
* 给子视图调用hitTest方法,返回一个fitView
* 如果第2步返回的fitView为真的话,就return 该fitView,否则返回nil
4. 子视图中没有找到退出了循环,返回self,自己就是hitTestView
代码演示
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
if (!self.userInteractionEnabled||self.hidden==YES||self.alpha<0.01) {
return nil;
}
if (![self pointInside:point withEvent:event]) {
return nil;
}
for (int i = 0; i<self.subviews.count; i++) {
UIView *childView = self.subviews[i];
CGPoint childPoint = [self convertPoint:point toView:childView];
if ([childView hitTest:childPoint withEvent:event]) {
return childView;
}
}
return self;
}
处理事件
1. 前提
* 重写了UIResponse的touch系列方法
**touch系列方法中touchbegin一点要调用**
* button的addtarget
* textField的becomFirstResponser
2. nextResponser
* 当前视图是一个普通view,nextResponser就是其父view
* 当前视图是一个控制器的view, nextResponser就是其控制器但是如果想要在viewDidLoad方法中打印出view的nextResponser是行不通,因为这个方法调用时间比较早,座椅可以推迟一些时间
拦截事件
* 在UIApplication中拦截,事件就不会被分发下去,重写其sendEvent方法,实现事件的过滤
* 在离他最近的父view中也可以,重写hitTest::方法
事件处理顺序
1. view-fatherView->fatherViewController->window->UIApplication->UIApplelegate->废弃