Search code examples
iosuiviewmulti-touchuitouchtouches

UITouches "lost" during multitouch


I'm having trouble getting a UIView to respond how I want with multiple touches. Basically certain UITouches are in UITouchPhaseBegan but never make it to UITouchPhaseEnded or UITouchPhaseCancelled. Here's the code I'm using to handle touches, which is called from touchesBegan:withEvent, touchesMoved:withEvent, touchesEnded:withEvent and touchesCancelled:withEvent. If I put one finger down, then another, move them, and release them simultaneously, the NSLog output is sometimes Began! Began! Ended! rather than Began! Began! Ended! Ended!. Are these touches getting lost somewhere? How can I keep track of them?

- (void) handleTouchEvent:(UIEvent *)event {
    for( UITouch* touch in [event allTouches] ) {
        if( touch.phase == UITouchPhaseBegan ) {
            NSLog(@"Began!");
            if( ![m_pCurrentTouches containsObject:touch] )
                [m_pCurrentTouches addObject:touch];
            uint iVoice= [m_pCurrentTouches indexOfObject:touch];
            CGPoint location = [touch locationInView:self];
            m_pTouchPad->SetTouchPoint( location.x, location.y, iVoice );
            m_pTouchPad->SetIsTouching( true, iVoice );
        }
        else if( touch.phase == UITouchPhaseMoved ) {
            uint index= [m_pCurrentTouches indexOfObject:touch];
            CGPoint location = [touch locationInView:self];
            m_pTouchPad->SetTouchPoint( location.x, location.y, index );
        }
        else if( touch.phase == UITouchPhaseEnded || touch.phase == UITouchPhaseCancelled ) {
            uint index= [m_pCurrentTouches indexOfObject:touch];
            [m_pCurrentTouches removeObject:touch];
            NSLog(@"Ended!");
            m_pTouchPad->SetIsTouching( false, index );
        }
    }
}

EDIT:

I'm offering a bounty because I really want a good solution to this. To summarize: I need a system where every touch that begins also ends, so if a user puts down one finger and then another elsewhere, I can see both touches begin, and by the time there are no fingers in contact with the device anymore, I have seen both touches end.

Am I pursuing the wrong strategy to achieve this?


Solution

  • One event can report many touches. So you are sometimes getting "Ended!" once, because only one event arrived and only one touch event handler call was made - but it reported both touches ending. If you are manually handling multiple simultaneous touches (fingers), it is up to you to track each touch individually and check every touch in every event to see how many of your touches are being reported and decide what to do.

    Apple has sample code showing how to do this by maintaining a CFDictionaryRef:

    http://developer.apple.com/library/IOs/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/MultitouchEvents/MultitouchEvents.html#//apple_ref/doc/uid/TP40009541-CH3-SW7

    (Scroll down to the section called "Handling Multitouch Events".)