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

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

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

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (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里传递:

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

DONE!