views:

180

answers:

2

Hello, in iPhone SDK there are touchesBegan, touchesEnded and touchesMoved functions that are called when a touch event appears. My problem is that when I put a finger on the screen and I'm not moving it there is no way to know if there is a finger on the screen or not. Is there a way to get current touch screen state?

In any of touchesBegan, touchesEnded and touchesMoved functions I can use fallowing code to know the state for every touch, but outside them I can't:|

NSSet *allTouches = [event allTouches];
for(GLuint index = 0; index < [allTouches count]; ++index)
{
    UITouch *touch = [[allTouches allObjects] objectAtIndex:index];
    if([touch phase] != UITouchPhaseCancelled)
    {
        CGPoint touchPoint = [touch locationInView:self];
        //do something with touchPoint that has state [touch phase]
    }
}
+1  A: 

You should keep a list of all points where the touches currently are. Make sure you don't just retain the UIEvent or UITouch objects (they're not guaranteed to live long) - instead, create your own data data structure. Odds are all you need is to keep track of the points where touches are currently down.

Jesse Beder
If I keep track to all touches there will be another problems1) After the last touch there is no way to update track class state and it will remain in an invalid state of "touch released"2) If you solve 1) by updating track class states on a timer there is a chance that you will remove "release" events before they were used and have an unresponsive application.
Felics
@Felics, I think you're misunderstanding my suggestion. Don't keep the list to try to mimic release events - still handle the touch released event as normal (send a message to some object, etc.). The difference is that you maintain a list of touch positions that you can query whenever you want.
Jesse Beder
I wanted to be able to query also their states from my objects instead to send events to objects(a bad architecture from the beginning but it can't be changed now, it is used in hundreds of source files:|). And my problem is with my last release event if I don't update track class on a timer because it will be invalid or with not handling all events if I update track class on a timer by deleting all release events... I know that this problem will be trivial to solve by sending events instead of querying states, but now it can't be solved like this.
Felics
@Felics, if you insist on querying, then you'll just have to keep the touch down state until everyone who needs it have checked it. That's up to you, depending on how you're set up; one possibility is to keep a map of querier -> touch event, and don't get rid of the touch event until every querier has asked for it. Or have the querier pass its last known state when it queries, and then you can return the next touch event.
Jesse Beder
The problem to do so is that I can't know who queries the input states, because my UI may change at run time and objects that are not visible are not updated. With events there is fallowing case: I put one finger on a button, the button receives Tap event.I put second finger on the same button, the button receives Tap event.I lift one finger, the button receives Release event and it's current state is "Not Pressed", but this in not correct because I have one finger over it.The problem may be solved by querying input states, but...
Felics
A: 

If you don't want to fix your broken design, why doesn't keeping a running list of active touches solve your problem?

NSMutableSet *touches;

In touchesBegan you add them, in touchesEnded and touchesCancelled you remove them...

You might use a "global" object (i.e. singleton) to track those and synchronize data access. I cannot see how querying this set would be different than asking UIKit directly for this information.

If you need information on touches on standard UIKit objects (i.e. UIButton), you probably need to subclass those - and I am not sure if you can get the desired effect with all classes (as they - or their subviews - could handle touches in any way they want).

Eiko