Iphone 手势识别器和按钮动作

Iphone 手势识别器和按钮动作,iphone,uibutton,conflict,uigesturerecognizer,ibaction,Iphone,Uibutton,Conflict,Uigesturerecognizer,Ibaction,我的视图层次结构如下所示: UIView (A) UIView > UIImageView UIView > UIView (B) UIView > UIView (B) > Rounded Rect Button UIView > UIView (B) > UIImageView UIView > UIView (B) > UILabel 我已将手势识别器连接到UIView(B)。我面临的问题是,对于UIView(B)中的Rounded Rec

我的视图层次结构如下所示:

UIView (A)
UIView > UIImageView
UIView > UIView (B)
UIView > UIView (B) > Rounded Rect Button
UIView > UIView (B) > UIImageView
UIView > UIView (B) > UILabel
我已将手势识别器连接到UIView(B)。我面临的问题是,对于UIView(B)中的Rounded Rect按钮,我没有得到任何操作。singleTap手势识别器捕获/覆盖按钮的触动内部事件

我怎样才能让它工作?我认为响应者链层次结构将确保按钮触摸事件将被优先考虑,它将被触发!我错过了什么

以下是一些相关代码:

#pragma mark -
#pragma mark View lifecycle (Gesture recognizer setup)

- (void)viewDidLoad {
    [super viewDidLoad];

    // double tap gesture recognizer
    UITapGestureRecognizer *dtapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapGestureRecognizer:)];
    dtapGestureRecognize.delegate = self;
    dtapGestureRecognize.numberOfTapsRequired = 2;
    [self.viewB addGestureRecognizer:dtapGestureRecognize];

    // single tap gesture recognizer
    UITapGestureRecognizer *tapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureRecognizer:)];
    tapGestureRecognize.delegate = self;
    tapGestureRecognize.numberOfTapsRequired = 1;
    [tapGestureRecognize requireGestureRecognizerToFail:dtapGestureRecognize];
    [self.viewB addGestureRecognizer:tapGestureRecognize];

    // add gesture recodgnizer to the grid view to start the edit mode
    UILongPressGestureRecognizer *pahGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureRecognizerStateChanged:)];
    pahGestureRecognizer.delegate = self;
    pahGestureRecognizer.minimumPressDuration = 0.5;
    [self.viewB addGestureRecognizer:pahGestureRecognizer];

    [dtapGestureRecognize release];
    [tapGestureRecognize release];
    [pahGestureRecognizer release];
}

#pragma mark -
#pragma mark Button actions

- (IBAction)buttonTouchUpInside:(id)sender {
    NSLog(@"%s, %@", __FUNCTION__, sender);
}

#pragma mark -
#pragma mark Gesture recognizer actions


- (void)singleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
    NSLog(@"%s", __FUNCTION__);
}

- (void)doubleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
    NSLog(@"%s", __FUNCTION__);
}

- (void)longPressGestureRecognizerStateChanged:(UIGestureRecognizer *)gestureRecognizer {

    switch (gestureRecognizer.state) {

        case UIGestureRecognizerStateEnded: {
            NSLog(@"%s", __FUNCTION__);

            break;
        }
        default:
            break;
    }
}
在“shouldReceiveTouch”方法中,您应该添加一个条件,如果触摸在按钮中,该条件将返回NO

这是来自苹果的例子

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {

    // Disallow recognition of tap gestures in the segmented control.
    if ((touch.view == yourButton)) {//change it to your condition
        return NO;
    }
    return YES;
}
希望能有所帮助

编辑

正如Daniel指出的,您必须遵守
UIgestureRecognitizerDelegate
,它才能工作


沙尼

我也有同样的问题,然后我试着用

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{

    if ([touch.view isKindOfClass:[UIButton class]]) {      //change it to your condition
        return NO;
    }
    return YES;
}

它现在工作得很好………

一般来说,我们使用下面的委托方法来避免各种uicontrol中的触摸:

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

注意:不要执行此检查(检查recognizer.view类类型)GestureRecognitizer应该开始,它不会工作。

我认为最好的解决方案是使用下面的代码片段:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    CGPoint touchLocation = [touch locationInView:self.view];
    return !CGRectContainsPoint(self.menuButton.frame, touchLocation);
}

以下是Swift版本:

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
    if (touch.view!.isKindOfClass(UIButton)) {
        return false
    }
    return true
}
别忘了:

  • 使您的类符合
    UIgestureRecognitizerDelegate
  • 将tapper对象委托给self(例如:
    tapper.delegate=self

  • 这是一个Swift 3.0版本:

    extension UIViewController: UIGestureRecognizerDelegate {
    
    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        if touch.view is UIButton {
            return false
        }
        return true
    }
    
    别忘了:


    将您的tapper对象委托给self(例如:tapper.delegate=self)

    啊!!!是的,我忘记了这个-手势识别器:shouldReceiveTouch:方法。谢谢你给我指明了正确的方向。虽然这解决了我的问题,但我仍然不知道为什么响应者层次结构在这种情况下不起作用。它可能应该这样做,但苹果没有处理它。UIgestureRecognitor的行为被清楚地描述为与“正常”响应程序链分离。这是Apple的一个设计决定。记住遵照UigesturrErgOngIZError协议并将uigesturreCngnisher的委托设置为该对象。为了更广泛的使用,请考虑Ramesh或FrigBoT的测试子句的一些变体。例如,在我的例子中,我以以下行结束:
    如果([touch.view isKindOfClass:[UIControl类]]| |[[touch.view superview]isKindOfClass:[UITableViewCell类]]){
    …注意tableview单元格被“触摸”在他们的contentView中,它是一个私有类的成员,因此我们在这里检查superview的类。谢谢你的回答!在我的情况下,我遇到了相同的问题,但直到我在实际设备中进行测试后才发现它。在模拟器中运行应用程序而不使用UIGestureDelegate,如回答中所示,效果与预期一样虽然不正确。我只错过了
    myGestureRecognizer.delegate=self;
    最简单的方法是将cancelsTouchesInView=false