响应链:
第一响应者到application对象的一系列响应者形成的链条
如何寻找第一响应者:
1、当iOS程序发生触摸事件后,系统会将事件加入到UIApplication的任务队列中
2、UIApplication分发触摸事件到UIWindow,然后UIWindow依次向下分发给UIView
3、UIView调用hitTest:withEvent:
方法看看自己能否处理事件,以及触摸点是否在自己上面。
4、如果满足条件,就遍历UIView上的子控件。重复上面的动作。
5、直到找到最顶层的一个满足条件的子控件,此子控件就是我们需要找到的第一响应者。
hitTest:withEvent:的处理流程
1、首先调用当前视图的pointInside:withEvent:方法判断触摸点是否在当前视图内;
2、若返回NO,则hitTest:withEvent:返回nil;
3、若返回YES,则向当前视图的所有子视图(subviews)从上往下发送hitTest:withEvent:消息
4、若有子视图返回非空对象,则hitTest:withEvent:方法返回此对象,处理结束;
5、如所有子视图都返回非,则hitTest:withEvent:方法返回自身(self)。
hitTest:withEvent:方法的伪代码
//返回最适合处理事件的视图,最好在父视图中指定子视图的响应
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if (!self.userInteractionEnabled || !self.hidden || self.alpha <= 0.01) {
return nil;
}
if ([self pointInside:point withEvent:event]) {
for (UIView *subView in [self.subviews reverseObjectEnumerator]) {
CGPoint subPoint = [subView convertPoint:point fromView:self];
UIView *bestView = [subView hitTest:subPoint withEvent:event];
if (bestView) {
return bestView;
}
}
return self;
}
return nil;
}
事件的响应流程
事件的响应流程1.首先通过 hitTest:withEvent: 确定第一响应者,以及相应的响应链
2.判断第一响应者能否响应事件,如果第一响应者能进行响应则事件在响应链中的传递终止。如果第一响应者不能响应则将事件传递给父试图或者控制器
3.如果事件继续上报至UIWindow并且无法响应,它将会把事件继续上报给UIApplication
4.如果事件继续上报至UIApplication并且也无法响应,它将会将事件上报给其Delegate
5.如果最终事件依旧未被响应则会被系统抛弃
借鉴:
iOS开发:浅谈响应链与事件传递
网友评论