解决UIGestureRecognizer会阻断SubView的Touch事件的问题

为一个View添加UIGestureRecognizer事件,会block所有SubViews的Touch事件,也就是说Touch事件先到UIGestureRecognizer,默认不会往子View继续传递。

画个图说明一下在我现在项目中的一个使用场景:

用一个UIWindow做了一个弹出效果,里面添加了一些子View完成一些操作,这里为了简单,用一个UIButton表示。要达到的效果是点击Button可以触发特定动作,点击Button以外区域则隐藏整个弹出层。

代码如下:

- (UIWindow *)dimmingWindow {
    if (!_dimmingWindow) {
        _dimmingWindow = [[UIWindow alloc] initWithFrame: [UIApplication sharedApplication].keyWindow.frame];
        _dimmingWindow.backgroundColor = [UIColor colorWithWhite:0 alpha:0.2];
        UIGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dimmingWindowTapped:)];
        gesture.delegate = self;
        [_dimmingWindow addGestureRecognizer:gesture];
    }
    
    return _dimmingWindow;
}

- (void)dimmingWindowTapped:(UITapGestureRecognizer *)sender {
    [_dimmingWindow setHidden:YES];
}

上面的代码效果是,点击弹出层的任何区域都会隐藏,但不会触发Button的点击事件。

如何解决?其实我们可以通过UIGestureRecognizerDelegate来判断当前的点击区域,然后决定要不要把Touch事件往子View里传递:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if (![touch.view isKindOfClass:[UIWindow class]]) {
        return NO;
    }
    return YES;
}

DONE!