iOS теряет прикосновения?

Я не могу найти ничего, чтобы объяснить потерянные события UITouch. Если вы ударите всей рукой по экрану достаточное количество раз, количество касаний Began будет отличаться от количества касаний Enaked! Я думаю, что единственный способ узнать об этих потерянных прикосновениях - это самому сослаться на них и отслеживать, как долго они не двигались.

Образец кода:

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];
}

person Joe Beuckman    schedule 16.02.2012    source источник
comment
Обновил мой ответ, чтобы включить новую теорию.   -  person Tim    schedule 26.04.2012
comment
Я уверен, что вы получите больше ответов, если исправите свой рейтинг приема. В настоящее время это 0%.   -  person Zar    schedule 26.04.2012


Ответы (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);
}

Каждое отдельное событие касания проходит через фазы запуска и завершения / отмены, поэтому ваши счета должны совпадать, как только ваши пальцы оторвутся от экрана.

person Tim    schedule 16.02.2012
comment
У меня есть следующее: - (void) touchesCancelled: (NSSet *) касается withEvent: (UIEvent *) event {[self touchesEnded: касается withEvent: event]; } (сейчас добавлен в исходный образец кода) - person Joe Beuckman; 17.02.2012
comment
Иногда не вызывается ни завершено, ни отменено - это ошибка в iOS - person jjxtra; 09.04.2017

Одна вещь, которую следует запомнить ... Вы можете получать касания, которые требуют нескольких нажатий. Не забудьте учесть tapCount.

Однако, если у вас все еще есть проблема, вы можете учесть все моменты, связанные с мероприятием, хотя оно представляет некоторые другие проблемы управления ...

ОПОВЕЩЕНИЕ О ВЗЛОМАХ

Чтобы обойти эту проблему, я закодировал следующий ХАК. Иногда touchEnded не вызывается, НО прикосновения отображаются как часть всех прикосновений в событии.

Обратите внимание, что теперь вы можете обрабатывать одно и то же касание «отменено» или «завершено» несколько раз. Если это проблема, вы должны сохранить свое собственное состояние «ожидающих» касаний и удалить их, когда закончите.

Да, все довольно плохо, но я не знаю, как решить эту проблему без подобного взлома. Основное решение - смотреть на все касания в каждом событии и обрабатывать их в зависимости от их фазы, вызывая соответствующие завершенные / отмененные, когда они видны.

- (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];
}

Затем вызовите его в конце TouchBegan и TouchMoved ...

[self touchesEndedOrCancelled:event.allTouches];

Для того, чтобы это сработало, touchEnded / Canceled не должно подавляться нулевым событием. Кроме того, нужно разобраться с «другим». В прикосновениях

[self touchesCancelled:[event.allTouches objectsPassingTest:^BOOL(UITouch *touch, BOOL *stop) {
    return touch.phase == UITouchPhaseCancelled;
}] withEvent:nil];

и в touchCanceled ...

[self touchesEnded:[event.allTouches objectsPassingTest:^BOOL(UITouch *touch, BOOL *stop) {
    return touch.phase == UITouchPhaseEnded;
}] withEvent:nil];
person Jody Hagins    schedule 20.04.2012

Возможно, вам потребуется предоставить более подробную информацию, но ....

Если вы проведете пальцем по краю экрана, это событие покажет, что касание началось, а касание переместилось, но без конца, так как на самом деле оно не закончилось (поднимите палец). Это может быть ваша проблема, что события не произошло. Кроме того, существует ограничение на количество касаний в мультитач, если вы нажмете, скажем, 10 раз, затем система, чтобы определить, какие события на самом деле, а какие ложные, похоже, вы неправильно используете оборудование.

person Dev2rights    schedule 26.04.2012