事件传递和响应链

UIResponder官方文档

App通过responder object 来接收和处理事件, UIResponder是responder object的基类;包括UIView,UIWindow,UIWindow,UIApplication及他们的子类。

事件传递传递:

当我们触摸屏幕时, 该触摸时间会添加到UIApplication管理的事件队列(称为队列的原因时先进先出)中,按顺序取出最早事件(先进先出),通过下面方法找到所触摸的视图,

- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;   // recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system

- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;   // default returns YES if point is in bounds

具体使用如下(猜测,肯定不止这些内容)

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    if (!self.userInteractionEnabled || self.isHidden || self.alpha <= 0.01) {
        return nil;
    }
    if ([self pointInside:point withEvent:event]) {
        for (UIView *view in self.subviews) {
            CGPoint convertedPoint = [view convertPoint:point fromView:self];
            return [view hitTest:convertedPoint withEvent:event];
        }
    }
    return nil;
}

userInteractionEnabled 不能交互  isHidden隐藏 alpha小于0.01的视图都不能响应,所以过滤掉。

具体传递顺序如下: UIWindow开始知道找到可以响应并且触摸点在View的bouns内的视图 

响应链:

查看响应链

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [super touchesBegan:touches withEvent:event];
    UIResponder *responder = self;
    while (responder) {
        NSLog(@"%@",responder.class);
        responder = responder.nextResponder;
    }
}

图片来源

响应链如上图

UITextField不响应,找UITextField的parentView, 直到找到响应着为止

响应方法

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;

猜你喜欢

转载自blog.csdn.net/wangchuanqi256/article/details/89381968