要记住的一件事...您可能会收到一些具有多次点击的触摸。不要忘记将 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 事件上阻塞。此外,需要处理“其他”。在接触结束...
[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];