touchesEnded 或 touchesCancelled 并不总是被调用

Posted

技术标签:

【中文标题】touchesEnded 或 touchesCancelled 并不总是被调用【英文标题】:touchesEnded or touchesCancelled not always called 【发布时间】:2012-12-18 20:03:53 【问题描述】:

我认为这个问题值得提出自己的问题。使用我对another problem 的解决方案附加的代码,我发现了此处描述的问题。

我将主视图控制器设置为 UIGestureRecognizerDelegate,并实现 touchesBegantouchesMovedtouchesEndedtouchesCancelled 对我的解决方案进行编程,假设每个触摸对象都带有 touchesBegan 事件对于同一对象,将有一个 touchesEndedtouchesCancelled 事件。不过,我发现情况并非如此。

场景: 以下事件按此顺序发生。

用户开始手势 1,触摸屏幕并滑动手指。

用户开始手势 2,在不同的位置触摸屏幕。

用户继续在屏幕的相应部分滑动两个手指。

用户将手指从屏幕上抬起以执行手势 2。

用户继续手势 1。

用户将手指从屏幕上抬起以执行手势 1。

使用NSLog捕获触摸事件的细节,我发现手势1和手势2使用了单独的触摸对象。但是touchesBegantouchesMovedtouchesEnded都被调用了手势 1,只有 touchesBegantouchesMoved 被手势 2 调用。事件 touchesCancelled 也没有被调用。

如果没有调用 touchesEndedtouchesCancelled,我如何判断手势 2 何时结束?

编辑:我发现 another post 有类似的症状。不过,我的大多数子视图都是以编程方式创建的。我会尝试那里为其他人建议的。不过,我怀疑这是同一个问题,因为在我的测试中,触摸位置不在其他视图附近。

另一个编辑:按照我之前编辑中发布的链接中的建议,我查看了子视图,其中一个已检查用户交互。取消选中后,行为略有不同。现在,在任何触摸事件中都不会注意到第二次触摸。我一定缺少一些基本的东西。顺便说一下,主视图和检查用户交互的视图都占用相同的空间(一个封装另一个)。

【问题讨论】:

您在使用界面生成器吗?如果是这样,请确保为那里的触摸正确设置了连接。 我看不出该评论如何适合所呈现的场景。如果连接有问题,总会有问题,而不是有时,对吧?但是,在回答您的问题时,主视图控制器是使用 UIViewController 的子类在情节提要中创建的。所有代码都在这个子类 .m 文件中。另外,有什么可以连接的?我还通过情节提要添加了一个轻按手势识别器以进行双击,并且它可以正常工作。 如果您现在一次只接收一次触摸,则很有可能将multipleTouchEnabled 设置为NO。您可以在 IB 或代码中将其设置为 YES,在 IB 中称为“Multiple Touch”。 @NJones,我尝试在代码中执行此操作,但没有成功。所以我检查了故事板并寻找你建议的领域。没查,所以查了。这解决了问题。所以现在我的问题是为什么没有调用代码?我明天(呃,今天晚些时候)将重读 Apple 的文档,希望能回答这个问题。 有趣。它仍然没有工作,但出于不同的原因。第一次和第二次触摸的点链不同。对于第一次触摸,当前点始终与下一步的前一个点匹配。对于第二次触摸,除了结尾之外的所有内容都是如此,它与前一点相匹配(因此我的代码没有选择它,例如最后移动:558.5, 817.5 --->> 558.5, 814.5并结束:558.5, 817.5 --->> 558.5, 814.5 用于第二次触摸并移动:175.5, 197.5 --->> 175.5, 199 并结束:175.5, 199 --- >> 176.5, 200.5 第一次触摸。 【参考方案1】:

我最初的假设是每个触摸都有自己的对象,从touchesBegan 开始,以touchesEndedtouchesCancelled 结束,我认为是正确的。无论如何,它与我当前的实现有关。我最初没有看到第二次触摸,因为没有为我正在使用的视图启用多点触摸。根据 cmets 中的建议,我启用了该功能。在那之后,我能够看到第二次触摸的一些,但不是所有的触摸事件。我有时看不到第二次触摸的原因是因为我有一个启用了用户交互的子视图。显然,它在控制触摸。我取消选中它,然后能够看到触摸对象。

然后,我将通过坐标跟踪触摸切换为触摸 ID,并能够跟踪所有触摸的完整生命周期。通过坐标跟踪不起作用,因为我发现对于第二次触摸,touchesEnded 坐标与touchesMoved 中的最后一个坐标相同,而不是touchesEnded 中的前一个位置与touchesMoved 中的touchLocation 匹配。第一次接触。如果这听起来令人困惑,只需通过触摸 ID 而不是坐标来跟踪触摸。

【讨论】:

【参考方案2】:

你如何在你的 touchesMoved 方法中加入这样的东西

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

    NSArray* touchData = @[touches,event];
    [self.timer invalidate];
    self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self
                  selector:@selector(touchesFinishedWithoutCallback:) userInfo:touchData
                  repeats:NO];
    [self.timer fire];

touchesFinishedWithoutCallback: 方法只会在 touchesMoved 停止被调用时被调用。

需要详细说明多点触控,但可能是一个解决方案?

【讨论】:

有趣的想法。我认为对于我的特定应用程序来说,这是一个杂乱无章的东西,而不是一个很好的东西。该应用程序是一款多用户、单设备、快速动作游戏。这两个触摸事件很可能是由竞争对手进行的。在您的场景中,第一个玩家可以通过按住手指来压制第二个玩家。不好。编辑:也许是相同的想法,但在没有听到特定触摸对象而不是事件之后。

以上是关于touchesEnded 或 touchesCancelled 并不总是被调用的主要内容,如果未能解决你的问题,请参考以下文章

在滚动视图上拖动视图:已收到 touchesBegan,但没有 touchesEnded 或 touchesCancelled

touchesEnded 坏了 UIScrollView

从 touchesEnded 获取图像名称

touchesEnded:withEvent: 来自 UIScrollView 第一响应者

调用 touchescancelled 而不是 touchesended

如何启用/禁用 touchesMoved、touchesEnded 和 Swipe Gestures