Количество начатых касаний не равно количеству готовых штрихов
У меня есть следующий код для тестирования:
- (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
.
UPDATE
Как многие из вас не могут воспроизвести это странное поведение, я подготовил образец проекта 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
Ответы
Ответ 1
Также есть проблема.
Только решение, которое я нашел в этот момент, основываясь на наблюдении сенсорной фазы:
- (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"];
}
}
}
Ответ 2
Похоже, это ошибка в методе SKView touchesBegan:
. Из того, что я могу сказать, Apple использует словарь для связывания каждого UITouch
с объектом, к которому должны быть отправлены методы касания. Из моего тестирования кажется, что если есть несколько касаний, которые начинаются в одно и то же время, только один из штрихов добавляется в словарь. В результате ваша сцена никогда не будет получать вызовы, связанные с касанием, для других касаний, поэтому вы видите разницу между touchhesStarted и touchsFinished.
Если вы подклассифицируете SKView и переопределите метод touchesBegan:
, ваша сцена должна получить правильные вызовы.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
NSSet *newSet = [NSSet setWithObject:touch];
[super touchesBegan:newSet withEvent:event];
}
}
Это устранило проблему для меня, но возможно, что некоторые вызовы могут быть вызваны несколькими способами.
Ответ 3
Не могу комментировать, так что ответьте здесь. Вы можете распечатать все обработчики, как это, может быть, это помогает:
- (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);
}
Можно ли переключить (touch.phase) в obj-c? Является ли "или" во втором, если правильно оценивается, попробуйте использовать брекеты.
Ответ 4
Если вы используете более одного пальца, вы должны включить self.view.multipleTouchEnabled = YES;
в свой init
.
Я провел несколько обширных тестов с вашим кодом, и единственный раз, когда цифры не совпадают, это когда запись происходит очень быстро из комбинации одного или обоих пальцев. В этом случае iOS перестает отслеживать контакт с текущим состоянием.
Это очень похоже на то, что спрайт быстро и быстро перескакивает на другой спрайт, который иногда вызывает неправильное состояние контакта в didBeginContact.
В настоящее время вы не можете обойти это, используя несколько касаний. Если вы используете одно касание, ваш счет будет всегда (по крайней мере, в моих тестах).
Ответ 5
У меня была эта же проблема раньше (touchesEnded: withEvent: не вызывается).
Мое тестирование показало, что touchedEnded не был вызван в 100% случаев. Мое решение: поместите четыре метода обработки касания в файл AppDelegate.m и переместите штрихи в свой контроллер представления. Я понятия не имею, почему это работает, но после этого у меня не было никаких проблем.