首页 > 解决方案 > 为什么 UITapGestureRecognizer 永远不会在状态开始时被调用?

问题描述

如果您将UITapGestureRecognizer分配给UIView,则UIGestureRecognizerStateBegan在用户触摸视图时不会出现。

// Tap

_tapGestureRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self
                                            action:@selector(tap:)];
    
[_someView addGestureRecognizer:_tapGestureRecognizer];

相反,当用户执行点击时,识别器会直接跳转到UIGestureRecognizerStateEnded 。

我必须将该视图更改为UIButton并收听 touchDown 方法。

_someButton = [[UIButton alloc] init];
    
[_someButton addTarget:self action:@selector(touchDown:) forControlEvents:UIControlEventTouchDown];
    
[self addSubview: _someButton];

我不喜欢仅仅为此将UIView更改为UIButton 。

我可以改用 UITapGestureRecognizer 吗?

标签: iosuiviewuibuttonuigesturerecognizer

解决方案


让我首先说UITapGestureRecognizer文档清楚地告诉期待所有状态的回调。

对于手势识别,指定数量的手指必须点击视图指定的次数。尽管轻敲是离散的手势,但它们对于手势识别器的每个状态都是离散的。系统在手势开始时发送关联的动作消息,然后针对每个中间状态再次发送,直到(包括)手势的结束状态。处理点击手势的代码应该测试手势的状态,例如:

func handleTap(sender: UITapGestureRecognizer) {
    if sender.state == .ended {
        // handling code
    }
}

然而,它几乎没有意义(特别是在单击识别器的情况下)。您触摸了一个视图(添加了轻击手势),您还没有抬起手指,移动它等。系统在.touchDown事件发生时无法知道此交互将变成成功识别轻敲(需要抬起手指)。

本质上UITapGestureRecognizer(对于单点触摸)是一种.touchDown + .touchUp组合。.touchDown如果在拖动(.touchDragInside或)之后发生任何其他事情.touchDragExit,它可能会导致成功识别平移手势(tableView 滚动等)

您可以认为UITapGestureRecognizer 大致相当于按钮的.touchUpInside事件。按钮的.touchUpInside事件不会调用您的.touchDown事件函数,只有通过明确要求相同的事件才能接收该事件。

为什么文档会这样说?

也许系统能够识别.began其他场景的状态

  1. 多次点击手势 - 双击/三次点击(请参阅UITapGestureReconizer.numberOfTapsRequired

  2. 多点触控点击 - 2/3 手指点击(请参阅UITapGestureReconizer.numberOfTouchesRequired

如果您想了解更多信息,您必须为此测试其他场景。


推荐阅读