PanGesture 和 Tap Gesture 之间的冲突

Posted

技术标签:

【中文标题】PanGesture 和 Tap Gesture 之间的冲突【英文标题】:Conflict btwn PanGesture and TapGesture 【发布时间】:2016-08-08 17:21:36 【问题描述】:

我的应用由一副纸牌组成。卡片组中的大多数卡片都是在 draggableView 中制作的。我正在努力做到这一点,以便在屏幕上双击将使我在卡上的按钮消失/重新出现。阅读此post 后,我尝试尝试一下。我将 UITapGesture 放入了我的 draggableView 类的 initWithFrame 方法中,如下所示:

- (id)initWithFrame:(CGRect)frame
self = [super initWithFrame:frame];
if (self) 
    [self addSubviewFromNib];
    [self setupView];
    panGestureRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(beingDragged:)];
    cardWidth = frame.size.width;
    cardHeight = frame.size.height;
    type = 0;
    panGestureRecognizer.delegate = self;
    panGestureRecognizer.cancelsTouchesInView = NO;
    _backgroundScrollView.panGestureRecognizer.cancelsTouchesInView = NO;
    //...more code above....
    _backgroundScrollView.userInteractionEnabled = YES;
    tapGestureRecognizer = [[UITapGestureRecognizer alloc]   initWithTarget:_backgroundScrollView action:@selector(doubleTap)];
    tapGestureRecognizer.delegate = _backgroundScrollView;
    tapGestureRecognizer.numberOfTapsRequired = 2;
[_backgroundScrollView addGestureRecognizer:tapGestureRecognizer];
[self addGestureRecognizer:panGestureRecognizer];



 - (void) doubleTap: (UITapGestureRecognizer *)tapGesturerecognizer

    _mapButton.hidden = !_mapButton.hidden;
    _menuButton.hidden = !_menuButton.hidden;
    _phoneButton.hidden = !_phoneButton.hidden;
    reviewButton.hidden = !reviewButton.hidden;
    _shareButton.hidden = !_shareButton.hidden;




- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 

    // If the gesture recognizer is a UITapGestureRecongizer, but the other
    // gesture detected is a UIPanGestureRecognizer, require the
    // UITapGestureRecognizer to fail.
    if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] &&
        [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) 
        return YES;
     else 
        return NO;
    




- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

    if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) 
        return YES;
    
    if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) 
        UIPanGestureRecognizer *panGesture = (UIPanGestureRecognizer *)gestureRecognizer;
        CGPoint velocity = [panGesture velocityInView:self];
        return fabs(velocity.y) <= fabs(velocity.x);
    
    return YES;

但是,如果我双击,我会收到这个 sib abrt 错误:

 -[UITapGestureRecognizer velocityInView:]: unrecognized selector sent to instance 0x7f9f9a244230
 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITapGestureRecognizer velocityInView:]: unrecognized selector sent to instance 0x7f9f9a244230'

我假设这意味着 PanGestureRecognizer 和 TapGesture 识别器之间存在错误。我该如何解决?

编辑:仍未解决,但如果我将 tapGesture 添加到可拖动视图(因此,self)而不是 _backgroundScrollView,我会收到此错误:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[DraggableView doubleTap]: unrecognized selector sent to instance 0x7fefdd9e4f70'

其他编辑:我将它改回 backgroundScrollView,现在我得到这个错误:

[UIScrollView doubleTap]: unrecognized selector sent to instance 0x7fe5130af000

【问题讨论】:

也贴出平移手势相关的代码。另外请发布正确的代码,您在发布的代码中缺少右括号。 用更多代码更新了它 gestureRecognizerShouldBegin 将被调用,当手势识别器即将处理触摸时,它可能是点击手势,也可能是平移手势。你需要检查gestureRecogniser类型,然后继续, How to compare the types of gestures on ios?的可能重复 我尝试了该线程中提供的解决方案,但仍然得到相同的 sig abrt 错误:/ 【参考方案1】:

gestureRecognizerShouldBegin 将被调用,当手势识别器即将处理触摸时,它可能是点击手势,也可能是平移手势。您需要检查gestureRecogniser 类型,然后继续。

实现以下方法(取自here)以允许同时识别手势:

 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 

    // If the gesture recognizer is a UITapGestureRecongizer, but the other
    // gesture detected is a UIPanGestureRecognizer, require the
    // UIPanGestureRecognizer to fail.
    if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] &&
        [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]])  
       return YES;
     else 
       return NO;
    

在另一个委托方法中,崩溃原因告诉你:

-[UITapGestureRecognizer velocityInView:]: unrecognized selector sent to instance 0x7f9f9a2

velocityInView 被错误的手势类型调用,为避免此类错误,修改您的委托方法如下:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer 

  if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]])      
       return YES;
  
  if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]])  
       UIPanGestureRecogniser *panGesture = (UIPanGestureRecongiser *)gestureRecogniser;    
       CGPoint velocity = [panGesture velocityInView:self];
       return fabs(velocity.y) <= fabs(velocity.x);
  
   return YES;

【讨论】:

我实现了gestureRecognizer:(将UILongPressGestureRecognizer更改为UIPanGestureRecognizer)和gestureRecognizerShouldBegin,但仍然得到同样的错误:/ 你是否按照我的回答更改了gestureRecognizerShouldBegin? 是的,我把它改成了你上面给出的——仍然是同样的错误 好的,请用您刚才的尝试更新您的问题,我们会看看有什么问题。 我更新了gestureRecognizerShouldBegin 方法。请尝试一下。 @MaddieElizabeth【参考方案2】:

我的错误: 在我的 h 文件中,我需要使用 draggableView 作为 tapGesture 的委托,然后将 gestureRecognizer 插入 UIGestureRecognizerDelegate 协议,如下所示:

@protocol UIGestureRecognizerDelegate <NSObject>
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
@end

【讨论】:

以上是关于PanGesture 和 Tap Gesture 之间的冲突的主要内容,如果未能解决你的问题,请参考以下文章

从 Tap Gesture 中获取特定的集合视图单元格

当 UITextField 位于 UIScrollView 内时,使用 Tap Gesture 关闭键盘的问题。

Swift 3 - 带有 Tap Gesture 的图像视图

IB Tap Gesture Recognizer 总是从 Outlet Collection 返回第一个视图

如何在 Xamarin.Forms 中使用 Tap Gesture 调用另一个页面?

Swiftui 如何在 foreach 循环中对整行使用 Tap Gesture