【问题标题】:iOS Loses Touches?iOS失去联系?
【发布时间】:2012-02-16 23:54:54
【问题描述】:

我找不到任何东西来解释丢失的 UITouch 事件。如果您将整只手砸在屏幕上的次数足够多,则 touchesBegan 的次数将不同于 touchesEnded 的次数!我认为真正了解这些孤立触摸的唯一方法是自己参考它们并跟踪它们多久没有移动。

示例代码:

int touchesStarted = 0;
int touchesFinished = 0;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    touchesStarted += touches.count;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    touchesFinished += touches.count;
    NSLog(@"%d / %d", touchesStarted, touchesFinished);
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self touchesEnded:touches withEvent:event];
}

【问题讨论】:

  • 更新了我的回复以包含一个新理论。
  • 如果您修正接受评级,我相信您会收到更多答案。目前为 0%。

标签: iphone ios multi-touch uievent


【解决方案1】:

别忘了touchesCancelled: UIResponder reference

根据海报的更新进行编辑:

每个触摸对象都提供了它所处的阶段:

typedef enum {
    UITouchPhaseBegan,
    UITouchPhaseMoved,
    UITouchPhaseStationary,
    UITouchPhaseEnded,
    UITouchPhaseCancelled,
} UITouchPhase;

我相信,如果触摸在同一个触摸事件集中开始和结束,-touchesBegan:withEvent: 将被调用但将包含已结束或取消的触摸

然后,您应该将计数代码更改为如下所示:

int touchesStarted = 0;
int touchesFinished = 0;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self customTouchHandler:touches];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self customTouchHandler:touches];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self customTouchHandler:touches];
}
- (void)customTouchHandler:(NSSet *)touches
{
    for(UITouch* touch in touches){
        if(touch.phase == UITouchPhaseBegan)
            touchesStarted++;
        if(touch.phase == UITouchPhaseEnded || touch.phase == UITouchPhaseCancelled)
            touchesFinished++;
    }
    NSLog(@"%d / %d", touchesStarted, touchesFinished);
}

每个触摸事件都会经历开始和完成/取消这两个阶段,因此只要手指离开屏幕,您的计数就会匹配。

【讨论】:

  • 我确实有以下几点: - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { [self touchesEnded:touches withEvent:event]; }(现在添加到原始代码示例中)
  • 有时既没有结束也没有取消 - 这是 iOS 中的一个错误
【解决方案2】:

要记住的一件事...您可能会收到一些需要多次点击的触摸。不要忘记将 tapCount 考虑在内。

但是,如果您仍然有问题,您可以考虑事件的所有接触,尽管它会带来一些其他管理问题...

黑客警报

我编写了以下 HACK 来解决这个问题。有时 touchesEnded 不会被调用,但是,触摸显示为事件中所有触摸的一部分。

请注意,您现在可以多次处理相同的“取消”或“结束”触摸。如果这是一个问题,您必须保持自己的“待处理”触摸状态,并在完成后将其删除。

是的,这一切都很糟糕,但如果没有类似的黑客攻击,我不知道如何克服这个问题。基本的解决方案是查看每个事件中的所有触摸,并根据它们的阶段对其进行处理,在看到它们时调用适当的结束/取消。

- (void) touchesEndedOrCancelled:(NSSet *)touches
{
    __block NSMutableSet *ended = nil;
    __block NSMutableSet *canceled = nil;
    [touches enumerateObjectsUsingBlock:^(UITouch *touch, BOOL *stop) {
        if (touch.phase == UITouchPhaseEnded) {
            if (!ended) ended = [NSSet setWithObject:touch];
            else [ended addObject:touch];
        } else if (touch.phase == UITouchPhaseCancelled) {
            if (!canceled) canceled = [NSSet setWithObject:touch];
            else [canceled addObject:touch];
        }
    }];
    if (ended) [self touchesEnded:ended withEvent:nil];
    if (canceled) [self touchesCancelled:canceled withEvent:nil];
}

然后,在 touchesBegan 和 touchesMoved 结束时调用它...

[self touchesEndedOrCancelled:event.allTouches];

为此,touchesEnded/Canceled 需要不被 nil 事件阻塞。此外,需要处理“其他”。在 touchesEnded...

[self touchesCancelled:[event.allTouches objectsPassingTest:^BOOL(UITouch *touch, BOOL *stop) {
    return touch.phase == UITouchPhaseCancelled;
}] withEvent:nil];

在 touchesCanceled...

[self touchesEnded:[event.allTouches objectsPassingTest:^BOOL(UITouch *touch, BOOL *stop) {
    return touch.phase == UITouchPhaseEnded;
}] withEvent:nil];

【讨论】:

    【解决方案3】:

    您可能需要提供更多详细信息,但是......

    如果您将手指从屏幕边缘移开,此事件将显示触摸开始和触摸移动但没有结束,因为它实际上并未结束(抬起手指)。这可能是你的问题,事件没有发生。另外,如果您按 10 次多点触控的次数,那么多点触控的数量是有限制的,然后由系统来确定哪些事件是真实的,哪些是错误的,看起来您使用的硬件不正确。

    【讨论】:

      猜你喜欢
      • 2016-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-22
      • 2016-05-04
      • 1970-01-01
      • 2012-08-23
      • 1970-01-01
      相关资源
      最近更新 更多