开始触摸的计数不等于完成触摸的计数

时间:2014-04-16 09:52:16

标签: ios objective-c sprite-kit uitouch

我有以下代码用于测试目的:

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

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

- (void)touchesMoved:(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);
}

我认为当屏幕上没有触摸时,touchesStarted应始终等于touchesFinished,但我有一个非常奇怪的输出:

2014-04-16 13:44:27.780 App[5925:60b] 2 / 0
2014-04-16 13:44:27.911 App[5925:60b] 2 / 1

我用两根手指按下屏幕,然后几乎(但不是)同时释放它们。

我错过了什么吗?为我的视图启用了多个触摸功能。顺便说一句,视图为SKView,代码属于我的自定义SKScene

更新

由于很多人无法重现这种奇怪的行为,我已经准备了一个示例Xcode项目:https://www.dropbox.com/s/qmgxka1gtgwquio/TapTest.zip

尝试多次同时用两根手指敲击。你移开手指时touchesStarted必须等于touchesEnded,对吗?但他们不是。这是我的输出:

2014-04-24 12:49:06.359 TapTest[8207:60b] 1 / 0
2014-04-24 12:49:06.376 TapTest[8207:60b] 2 / 0
2014-04-24 12:49:06.458 TapTest[8207:60b] 2 / 0
2014-04-24 12:49:06.460 TapTest[8207:60b] 2 / 1
2014-04-24 12:49:06.491 TapTest[8207:60b] 2 / 2
2014-04-24 12:49:07.325 TapTest[8207:60b] 3 / 2
2014-04-24 12:49:07.342 TapTest[8207:60b] 4 / 2
2014-04-24 12:49:07.408 TapTest[8207:60b] 4 / 2
2014-04-24 12:49:07.410 TapTest[8207:60b] 4 / 3
2014-04-24 12:49:07.426 TapTest[8207:60b] 4 / 3
2014-04-24 12:49:07.441 TapTest[8207:60b] 4 / 4
2014-04-24 12:49:07.842 TapTest[8207:60b] 6 / 4
2014-04-24 12:49:07.925 TapTest[8207:60b] 6 / 4
2014-04-24 12:49:07.941 TapTest[8207:60b] 6 / 5
2014-04-24 12:49:08.042 TapTest[8207:60b] 8 / 5
2014-04-24 12:49:08.125 TapTest[8207:60b] 8 / 6
2014-04-24 12:49:08.259 TapTest[8207:60b] 9 / 6
2014-04-24 12:49:08.293 TapTest[8207:60b] 9 / 6
2014-04-24 12:49:08.308 TapTest[8207:60b] 9 / 7
2014-04-24 12:49:08.425 TapTest[8207:60b] 10 / 7
2014-04-24 12:49:08.442 TapTest[8207:60b] 11 / 7
2014-04-24 12:49:08.444 TapTest[8207:60b] 11 / 7
2014-04-24 12:49:08.492 TapTest[8207:60b] 11 / 8
2014-04-24 12:49:08.575 TapTest[8207:60b] 11 / 9
2014-04-24 12:49:08.642 TapTest[8207:60b] 12 / 9
2014-04-24 12:49:08.659 TapTest[8207:60b] 13 / 9
2014-04-24 12:49:08.660 TapTest[8207:60b] 13 / 9
2014-04-24 12:49:08.692 TapTest[8207:60b] 13 / 9
2014-04-24 12:49:08.694 TapTest[8207:60b] 13 / 10
2014-04-24 12:49:08.708 TapTest[8207:60b] 13 / 10
2014-04-24 12:49:08.741 TapTest[8207:60b] 13 / 11
2014-04-24 12:49:08.792 TapTest[8207:60b] 14 / 11
2014-04-24 12:49:08.809 TapTest[8207:60b] 15 / 11
2014-04-24 12:49:08.810 TapTest[8207:60b] 15 / 11
2014-04-24 12:49:08.890 TapTest[8207:60b] 15 / 11
2014-04-24 12:49:08.892 TapTest[8207:60b] 15 / 12
2014-04-24 12:49:08.908 TapTest[8207:60b] 15 / 13
2014-04-24 12:49:09.042 TapTest[8207:60b] 17 / 13
2014-04-24 12:49:09.141 TapTest[8207:60b] 17 / 14
2014-04-24 12:49:09.242 TapTest[8207:60b] 19 / 14
2014-04-24 12:49:09.341 TapTest[8207:60b] 19 / 14
2014-04-24 12:49:09.358 TapTest[8207:60b] 19 / 15
2014-04-24 12:49:09.441 TapTest[8207:60b] 21 / 15
2014-04-24 12:49:09.525 TapTest[8207:60b] 21 / 15
2014-04-24 12:49:09.542 TapTest[8207:60b] 21 / 15
2014-04-24 12:49:09.559 TapTest[8207:60b] 21 / 16
2014-04-24 12:49:09.608 TapTest[8207:60b] 22 / 16
2014-04-24 12:49:09.625 TapTest[8207:60b] 23 / 16
2014-04-24 12:49:09.626 TapTest[8207:60b] 23 / 16
2014-04-24 12:49:09.708 TapTest[8207:60b] 23 / 16
2014-04-24 12:49:09.709 TapTest[8207:60b] 23 / 17
2014-04-24 12:49:09.774 TapTest[8207:60b] 23 / 18
2014-04-24 12:49:09.810 TapTest[8207:60b] 24 / 18
2014-04-24 12:49:09.826 TapTest[8207:60b] 25 / 18
2014-04-24 12:49:09.828 TapTest[8207:60b] 25 / 18
2014-04-24 12:49:09.908 TapTest[8207:60b] 25 / 18
2014-04-24 12:49:09.909 TapTest[8207:60b] 25 / 19
2014-04-24 12:49:09.974 TapTest[8207:60b] 25 / 20
2014-04-24 12:49:09.992 TapTest[8207:60b] 26 / 20
2014-04-24 12:49:10.026 TapTest[8207:60b] 27 / 20
2014-04-24 12:49:10.027 TapTest[8207:60b] 27 / 20
2014-04-24 12:49:10.091 TapTest[8207:60b] 27 / 20
2014-04-24 12:49:10.094 TapTest[8207:60b] 27 / 21
2014-04-24 12:49:10.125 TapTest[8207:60b] 27 / 22

5 个答案:

答案 0 :(得分:2)

也有这个问题。

此时我发现只有基于观察触摸阶段的解决方案:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"Began %lu of %lu", [touches count], [event.allTouches count]);

    for (UITouch *touch in touches) {
        [touch addObserver:self forKeyPath:@"phase" options:0 context:nil];
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"Ended %lu of %lu", [touches count], [event.allTouches count]);
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

    if ([object isKindOfClass:[UITouch class]]) {
        UITouch *touch = object;
        NSLog(@"Touch %lu phase: %ld", (unsigned long)[touch hash], [touch phase]);
        if (touch.phase == UITouchPhaseEnded || touch.phase == UITouchPhaseCancelled) {
            NSLog(@"Touch %lu ended", (unsigned long)[touch hash]);
            [touch removeObserver:self forKeyPath:@"phase"];
        }
    }
}

答案 1 :(得分:1)

看来这是SKView touchesBegan:方法中的一个错误。据我所知,Apple正在使用字典将每个UITouch与触摸方法应转发到的对象相关联。从我的测试看来,如果有多个触摸同时开始,只有一个触摸被添加到字典中。因此,您的场景将永远不会接收其他触摸的触摸相关方法调用,这就是为什么您看到touchesStarted和touchesFinished之间的区别。

如果您继承SKView并覆盖touchesBegan:方法,则您的场景应该得到正确的调用。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    for (UITouch *touch in touches) {
        NSSet *newSet = [NSSet setWithObject:touch];
        [super touchesBegan:newSet withEvent:event];
    }
}

这解决了我的问题,但是多次调用super方法可能会产生一些副作用。

答案 2 :(得分:0)

无法评论,所以会在这里回答。你可以打印这样的所有处理程序,也许它会有所帮助:

- (void)customTouchHandler:(NSSet *)touches
{
    static int handlerCounter = 0;
    handlerCounter++;
    for(UITouch* touch in touches){
        NSLog(@"%d: %d", handlerCounter, touch.phase);
        if(touch.phase == UITouchPhaseBegan)
            touchesStarted++;
        if(touch.phase == UITouchPhaseEnded || touch.phase == UITouchPhaseCancelled)
            touchesFinished++;
    }
    NSLog(@"%d / %d", touchesStarted, touchesFinished);
}

是否可以在obj-c中切换(touch.phase)?是"还是"如果评估正确,请尝试使用托架。

答案 3 :(得分:0)

如果您使用多个手指,则应在self.view.multipleTouchEnabled = YES;中加入init

我对您提供的代码进行了一些广泛的测试,而且数字不匹配的唯一时间是从一个或两个手指的组合中非常快地进行编带。在这种情况下,iOS无法跟踪当前状态的联系。

这非常类似于sprite在另一个精灵上快速反弹,这有时会在didBeginContact中导致错误的联系状态。

目前无法通过多次触摸来解决这个问题。如果您只使用一次触摸,您的计数将始终(至少在我的测试中)匹配。

答案 4 :(得分:0)

我之前遇到过同样的问题(touchesEnded:withEvent: is not called)。

我的测试显示,touchEnded并非100%被调用。我的解决方案:将四种触摸处理方法放在AppDelegate.m文件中,并将触摸转发给视图控制器。我不知道为什么会这样,但我这样做后没有任何问题。