iOS теряет касания?
Я не могу найти ничего, чтобы объяснить потерянные события UITouch. Если вы ударите свою полную руку по экрану достаточно раз, количество касаний Began будет отличаться от количества касаний закругленных! Я думаю, что единственный способ узнать об этих осиротевших прикосновениях самому - это сослаться на них и отследить, как долго они не двигались.
Образец кода:
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];
}
3 ответа
Не забывайте о touchesCancelled
: Ссылка на UIResponder
Редактирование в ответ на обновление постера:
Каждый сенсорный объект указывает, в какой фазе он находится:
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);
}
Каждое сенсорное событие будет проходить через обе фазы: начатое и завершенное / отмененное, поэтому ваши показатели должны совпадать, как только ваши пальцы исчезнут с экрана.
Одна вещь, которую нужно помнить... Вы можете получить несколько касаний, которые имеют несколько нажатий. Не забудьте принять во внимание 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];
}
Затем, назовите его в конце прикосновения Начал и коснулся Перемещено...
[self touchesEndedOrCancelled:event.allTouches];
Чтобы это работало, touchesEnded/Cancelled не должно подавляться событием с нулевым значением. Кроме того, "другое" должно быть обработано. В касаниях закруглил...
[self touchesCancelled:[event.allTouches objectsPassingTest:^BOOL(UITouch *touch, BOOL *stop) {
return touch.phase == UITouchPhaseCancelled;
}] withEvent:nil];
и в контакте отменил...
[self touchesEnded:[event.allTouches objectsPassingTest:^BOOL(UITouch *touch, BOOL *stop) {
return touch.phase == UITouchPhaseEnded;
}] withEvent:nil];
Возможно, вам придется предоставить более подробную информацию, но....
Если вы проведете пальцем по краю экрана, это событие покажет, что касание запущено и касание перемещено, но не заканчивается, поскольку оно фактически не заканчивалось (поднимите палец). Это может быть вашей проблемой, что событие не произошло. Кроме того, существует ограничение на количество касаний в режиме мультитач, если вы нажимаете, скажем, 10 раз, а затем до системы, чтобы определить, какие события на самом деле, а какие ложные, кажется, что вы используете оборудование неправильно.