How to get number of active touches?

Member
Posts: 81
Joined: 2007.07
Post: #1
My problem is how can I tell in touchesEnded the difference between scenario 1 and 2? When touchesEnded is called I need some way of querying how many active touches are still on the screen, is there a call to do this?

Scenario 1:
User touches display with 2 fingers.
Lifts 1 finger.
touchesEnded is called with [allTouches count] = 2
Lifts other finger.
touchesEnded is called with [allTouches count] = 1

Scenario 2:
User touches display with 2 fingers.
Lifts both fingers at the same time.
touchesEnded is called with [allTouches count] = 2
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #2
Are you sure that it's possible to lift both fingers fast enough that they come in as one event? I would sort of guess that you will get a touches ended message for each finger, though I have nothing to back that up.

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #3
This isn't easy to explain or understand IMHO. I think my best advice would be to look in the iPhone Application Programming Guide, under Event Handling, and specifically the section on Touch Events. Read it carefully and you should hopefully be able to understand what's going on enough to discriminate between touches.

According to the Apple docs, you need to track each touch separately, in your own array or whatever, as the events show up. Additionally, when you copy data about the touch, you can't simply use an NSDictionary, since the UITouch doesn't comply with NSCopying, so the trick is to copy the address of each touch and use that to match up with the touches sent in each event.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #4
In scenario 1, the touch array passed to touchesEnded would only have 1 item both times: the particular touch that ended. It doesn't contain other touches that are in progress and not ending.
Quote this message in a reply
Member
Posts: 81
Joined: 2007.07
Post: #5
Skorche Wrote:Are you sure that it's possible to lift both fingers fast enough that they come in as one event? I would sort of guess that you will get a touches ended message for each finger, though I have nothing to back that up.

Yes, you can indeed. You can create both one touchesBegan and touchesEnd event when using multiple fingers.


ThemsAllTook Wrote:In scenario 1, the touch array passed to touchesEnded would only have 1 item both times: the particular touch that ended. It doesn't contain other touches that are in progress and not ending.

Untrue, I get both touches in the array. (Edit: I think you are right if you get the touches differently)


AnotherJake Wrote:This isn't easy to explain or understand IMHO. I think my best advice would be to look in the iPhone Application Programming Guide, under Event Handling, and specifically the section on Touch Events. Read it carefully and you should hopefully be able to understand what's going on enough to discriminate between touches.

According to the Apple docs, you need to track each touch separately, in your own array or whatever, as the events show up. Additionally, when you copy data about the touch, you can't simply use an NSDictionary, since the UITouch doesn't comply with NSCopying, so the trick is to copy the address of each touch and use that to match up with the touches sent in each event.

Yeah I did this and thought of tracking the touches via address, but don't know how to get an address in Objective C, and I don't see how this would fix the problem. Even if you have both addresses of the touches, when you get the touchesEnded event you still get both touches in the array, even though only 1 was ended, so saving the addresses isn't going to do you any good for knowing that one touch is still valid.
Quote this message in a reply
Member
Posts: 81
Joined: 2007.07
Post: #6
Maybe its a bug or I'm getting the touches incorrectly, here is my touch code.

Code:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch1, *touch2;
    CGPoint    location1, location2;

    NSSet *allTouches = [event allTouches];
    touch1 = [[allTouches allObjects] objectAtIndex:0];
    location1 = [touch1 locationInView:self];

    if([allTouches count] > 1)
    {
        touch2 = [[allTouches allObjects] objectAtIndex:1];
        location2 = [touch2 locationInView:self];
    }
}
Quote this message in a reply
Member
Posts: 81
Joined: 2007.07
Post: #7
aha, I just found this little gem which explains it.

To find out when the last finger in a multi-touch sequence is lifted from a view, compare the number of UITouch objects in the passed-in set with the number of touches for the view maintained by the passed-in UIEvent object. If they are the same, then the multi-touch sequence has concluded. Listing 3-9 illustrates how to do this in code.

Listing 3-9 Determining when the last touch in a multi-touch sequence has ended

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

if ([touches count] == [[event touchesForView:self] count]) {

// last finger has lifted....

}

}

Remember that the passed-in set contains all touch objects associated with the receiving view that are new or changed for the given phase whereas the touch objects returned from touchesForView: includes all objects associated with the specified view.
Quote this message in a reply
Moderator
Posts: 3,573
Joined: 2003.06
Post: #8
Getting the touch's address is simple (it's just a pointer):

Code:
NSArray *touchArray = [touches allObjects];
UITouch *touch1 = [touchArray objectAtIndex:0];
void *myAddressForTouch1 = touch1;
Quote this message in a reply
Moderator
Posts: 133
Joined: 2008.05
Post: #9
You can most definitely get two (or more) touches in one of the touch event methods - this is why NSSet is the type of the argument. Whether you get more than one touch object passed in a single message or spread out among multiple messages is a function of time: if the same event occurs for multiple fingers within a very short period of time (15ms if there is nothing else going on - across all devices so far), you get those touch objects in the same message.

As far as tracking the touch, you can simply use a dictionary. You will use the address of the touch object as the key.
Code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    for(UITouch *t in touches) {
        NSValue *key = [NSValue valueWithPointer:t];
        [startingLocations setObject:[NSValue valueWithCGPoint:[t locationInView:self]]
                              forKey:key];
    }
}
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  touches offset? Jamie W 11 11,540 Aug 18, 2011 10:23 AM
Last Post: MattDiamond
  not getting touches for top 20 pixels Rasterman 10 6,383 Apr 8, 2010 01:00 AM
Last Post: fattoh
  Touches are slowing down game Jamie W 8 5,637 Mar 26, 2010 03:41 PM
Last Post: Jamie W
  Touches Lagging & Skipping hippocoder 0 1,987 Mar 8, 2010 09:20 AM
Last Post: hippocoder
  Touches: Device vs Simulator vectorscope 4 4,458 Sep 22, 2009 03:25 PM
Last Post: Skorche