iOS中事件传递过程

  iOS中,UIApplication管理着一个事件的队列,当系统获取用户的点击或滑动等事件后,就会将这些事件按顺序插入UIApplication管理的这个队里中,UIApplication再从这个队列中取出事件传递给UIWindow,UIWindow传递给它的View,View继续传递给它的子视图。那么系统是如何正确的将这个事件传递到用户操作的视图上呢?

原来每一个UIView都拥有一个名为hitTest的方法,通过这个方法,UIview首先判断自己能接收事件,不能接收事件就不会继续将获取的事件传递给自己的子视图。如果自己能接收事件,UIView就会通过调用pointInside方法判断事件发生的那个点有没有在当前视图上。如果在当前视图上,UIView就会从从后往前遍历自己的子控件,判断有没有比自己更合适的View来接收该事件。

下面让我们来看看hitTest的具体实现过程吧:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    // 判断自己能否接收事件
    if (self.userInteractionEnabled == NO || self.alpha <= 0.01 || self.hidden == YES) {
        return nil;
    }
    
    // 判断点是不是在当前视图上
    if (![self pointInside:point withEvent:event]) {
        return nil;
    }
    
    // 从后往前遍历自己的子控件,寻找更合适的View
    for (long i = self.subviews.count - 1; i >= 0; i--) {
        // 获取子控件
        UIView *childView = self.subviews[i];
        
        // 将自己坐标系的点转化成子控件坐标系的点
        CGPoint childPoint = [self convertPoint:point toView:childView];
        
        // 递归调用hitTest方法,寻找更加合适的View
        UIView *fitView = [childView hitTest:childPoint withEvent:event];
        if (fitView) {
            return fitView;
        }
    }
    
    // 没有找到比自己更适合的View
    return self;
}

posted @ 2015-12-16 17:52  JM110  阅读(496)  评论(0编辑  收藏  举报