iPhone:Отслеживание /Идентификация индивидуальных штрихов

StackOverflow https://stackoverflow.com/questions/913086

Вопрос

У меня есть небольшой вопрос относительно отслеживания касаний на iPhone, и я, кажется, не могу прийти к какому-либо выводу по этому поводу, поэтому я очень ценю любые предложения / идеи:

Я хочу иметь возможность отслеживать и идентифицировать касания на iphone, т.е.по сути, каждое касание имеет начальную позицию и текущую / перемещенную позицию.Прикосновения хранятся в std::vector, и они должны быть удалены из контейнера, как только они закончатся.Их положение будет обновлено, как только они переместятся, но я все еще хочу отслеживать, с чего они изначально начали (распознавание жестов).

Я получаю штрихи из [event allTouches], дело в том, что NSSet не отсортирован, и я, похоже, не могу идентифицировать штрихи, которые уже сохранены в std:: vector, и ссылаются на штрихи в NSSet (поэтому я знаю, какие из них закончились и должны быть удалены, или были перемещены и т.д.).

Вот мой код, который, конечно, отлично работает только с одним пальцем на сенсорном экране, но с несколькими я получаю непредсказуемые результаты...

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

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

- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    [self handleTouches:[event allTouches]];
}

- (void) touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
{
    [self handleTouches:[event allTouches]];
}

- (void) handleTouches:(NSSet*)allTouches
{   
    for(int i = 0; i < (int)[allTouches count]; ++i)
    {
        UITouch* touch = [[allTouches allObjects] objectAtIndex:i];
        NSTimeInterval timestamp = [touch timestamp];

        CGPoint currentLocation = [touch locationInView:self];
        CGPoint previousLocation = [touch previousLocationInView:self];

        if([touch phase] == UITouchPhaseBegan)
        {
            Finger finger;
            finger.start.x = currentLocation.x;
            finger.start.y = currentLocation.y;
            finger.end = finger.start;
            finger.hasMoved = false;
            finger.hasEnded = false;

            touchScreen->AddFinger(finger);
        }
        else if([touch phase] == UITouchPhaseEnded || [touch phase] == UITouchPhaseCancelled)
        {
            Finger& finger = touchScreen->GetFingerHandle(i);

            finger.hasEnded = true;
        }
        else if([touch phase] == UITouchPhaseMoved)
        {
            Finger& finger = touchScreen->GetFingerHandle(i);

            finger.end.x = currentLocation.x;
            finger.end.y = currentLocation.y;
            finger.hasMoved = true;
        }
    }

    touchScreen->RemoveEnded();
}

Спасибо!

Это было полезно?

Решение

Чтобы устранить вашу проблему, откажитесь от своего метода "handleTouches".Первое, что вы делаете в своем методе handleTouches, это переключаете его на сенсорную фазу, но это вам уже дано.Если вы получаете касание в touchesBegan, вы знаете, что касание находится в UITouchPhaseBegan.Объединяя прикосновения из четырех методов касания в один метод, вы сводите на нет цель использования четырех методов делегирования.

В каждом из этих методов Apple дает вам возможность работать с другой фазой текущего касания.

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

Событие состоит из наборов касаний.Для удобства вам будут предоставлены текущие штрихи, хотя их также можно найти в event.

Итак, в touchesBegan вы начинаете отслеживать прикосновение.

    - (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event{


        NSString *startPoint = NSStringFromCGPoint([[touches anyObject] locationInView:self]);  

        NSDictionary * touchData = [NSDictionary dictionaryWithObjectsandKeys: startPoint, @"location", touches, @"touch"]

        [startingLocations addObject:touchData];

        }

Я использую массив словарей для хранения моих сенсорных данных.

Попробуйте отделить свой код и переместить его в соответствующий сенсорный метод.Например, у Apple есть пара примеров проектов, посвященных касаниям, и они показывают вам, как настроить эти методы.

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

Указатель на каждый набор касаний остается постоянным, меняются только данные.

Кроме того, я бы прочитал раздел руководства по программированию iPhone OS, посвященный обработке событий, в котором более подробно рассказывается о том, что я сказал выше, с несколькими диаграммами, объясняющими взаимосвязь касаний с событиями с течением времени.

Отрывок:

В iPhone OS объект UITouch представляет касание, а UIEvent объект представляет событие.Событие объект содержит все объекты касания для текущей последовательности мультитач и может предоставлять объекты касания, специфичные для вида или окна (см. рисунок 3-2). Объект касания является постоянным для данного пальца во время выполнения последовательности, и UIKit изменяет его при отслеживании пальца на всем протяжении.Атрибуты касания это изменение - фаза касания , его местоположение в представлении, его предыдущее местоположение и его временная метка.Код обработки событий оценивает эти атрибуты, чтобы определить, как реагировать на событие.

Другие советы

Похоже, что "правильный" способ отслеживать несколько касаний - по значению указателя события UITouch.

Вы можете найти более подробную информацию в разделе "Обработка сложной последовательности мультитач" этой Документация разработчика Apple

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

В вашем -handleTouches метод, вы могли бы поместить что-то подобное в свой цикл for:

// ..existing code..
CGPoint previousLocation = [touch previousLocationInView:self];

// Loop through previous touches
for (int j = 0; j < [previousTouchLocationArray count]; j++) {
  if (previousLocation == [previousTouchLocationArray objectAtIndex:j]) {
    // Current touch matches - retrieve from finger handle j and update position
  }
}

// If touch was not found, create a new Finger and associated entry 

Очевидно, вам нужно будет проделать некоторую работу, чтобы интегрировать это в свой код, но я почти уверен, что вы сможете использовать эту идею для правильной идентификации касаний по мере их перемещения по экрану.Также я только что понял, что CGPoint не будет хорошо вписываться в NSArray - вам нужно будет обернуть их в объекты NSValue (или использовать другой тип массива).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top