我找不到任何可以解释丢失的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 :(得分:5)
不要忘记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);
}
每一次触摸事件都会经历开始和结束/取消的两个阶段,因此一旦您的手指离开屏幕,您的计数就会匹配。
答案 1 :(得分:3)
要记住一件事......你可能会收到一些有多个水龙头的触摸。不要忘记考虑tapCount。
但是,如果您仍然遇到问题,可以考虑活动的所有内容,但它会提出一些其他管理问题......
HACK ALERT
我编写了以下 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];
答案 2 :(得分:0)
您可能需要提供更多细节,但......
如果您将手指从屏幕边缘移开,此事件将显示触摸开始并触摸移动但没有结束,因为它实际上没有结束(抬起手指)。这可能是你的问题,事件没有发生。此外,如果您按下10次然后按下系统以确定哪些事件确实是什么以及哪些是错误的,那么多点触控的触摸量是有限的,您似乎错误地使用了硬件。