如何防止子视图上的点击触发父视图上的 UITapGestureRecognizer?

How do I prevent taps on a subview from triggering a UITapGestureRecognizer on a parent view?

我向视图添加了点击识别器:

   UITapGestureRecognizer* tgr = [[UITapGestureRecognizer alloc]
      initWithTarget:self action:@selector( onTap )];
   [view addGestureRecognizer: tgr];

问题是点击 view 的子视图会触发 onTap。我该如何预防?

将子视图添加到视图的背景,并将点击手势识别器附加到子视图:

UIView* subview = [[UIView alloc] initWithFrame:view.bounds];
subview.backgroundColor = [UIColor clearColor];//or view.backgroundColor
[view addSubview:subview];
[view sendSubviewToBack:subview];
[subview addGestureRecognizer:tapRecognizer];

假设您的 parentView 有一个 subView。你实现下面的UIGestureRecognizerDelegate方法,如果触摸在subView的范围内,你return不

tgr.delegate = self;

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    CGPoint locationInView = [touch locationInView:self.parentView];
    if (CGRectContainsPoint(self.subView.frame, locationInView) ) {
        return NO;
    } else {
        return YES;
    }
}

Swift 4.2 回答 AlertView

添加手势识别器并设置委托:

let backgroundViewTapGesture = UITapGestureRecognizer(target: self, action: #selector(dismiss))
backgroundViewTapGesture.delegate = self     
self.backgroundView.addGestureRecognizer(backgroundViewTapGesture)
self.backgroundViewTapGesture = backgroundViewTapGesture

然后添加扩展程序来处理点击

extension AlertView: UIGestureRecognizerDelegate {

    // Only handle this for the background tap gesture
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        guard gestureRecognizer == backgroundViewTapGesture, let backgroundView = gestureRecognizer.view, let alertView = self.alertContentView else {
            return true
        }

        let touchLocation = touch.location(in: backgroundView)
        return !alertView.frame.contains(touchLocation)
    }
}

在Swift中:

public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    let locationInView = touch.location(in: mainView)
    if debugOptionsView.isHidden {
        return true
    }
    return !debugOptionsView.frame.contains(locationInView)
}