Since this was such a major obstacle for me, I thought I'd share my solution of how to recognize a touch and hold. No sense in others suffering like I did!
In one of the posts I made on these forums asking for help figuring out how to recognize a touch and hold, someone suggested storing the touch in a variable, starting a timer, and then examining the current touch and comparing it to the initial touch. A sound suggestion, except for the last part. As it turns out, I don't think reviewing the current touch is possible when you're talking about doing so outside of the touch event methods (touchesBegan, touchesMoved, and touchesEnded).
Instead, this is the approach I took - which is now working perfectly.
1) In my header file for the class that this code is running in (a UIViewController in my case), I've declared an NSTimer called "touchTimer" and synthesized it in the corresponding implementation file. That, of course, makes it a variable that is accessible across multiple methods in the implementation file.
2) In the touchesBegan event method add the timer to the run loop or call a method that will do so.
3) In the "touchHasBeenHeld" method that is called when the timer fires, do whatever you like to have happen when the touch has been held. However, after that functionality you'll need to invalidate the timer if it's currently valid and re-add the timer to the run loop.
That might seem odd to do... I mean, the code that's running here is in a method that is called when the timer fires (at which point the timer should not be valid). And why re-add it to the run loop? If you don't, you'll find that your application will lock up when you touch and hold and then move. I'm not sure I understand exactly why myself.
4) This one is probably obvious if you've read up to this point. In both the touchesMoved and touchesEnded event methods you'll need to invalidate the timer if it's currently valid. In the touchesMoved method, you'll also need to re-add the timer to the run loop just like you did inside the method that the timer triggers. Again, it doesn't really make sense to me just yet... but it prevents the app from locking up when you touch and move. This is not necessary to do in the touchesEnded event method.
Right now I've got a UILabel that I put text into when the touch starts, when it moves, when it ends, and when it's been held for a set number of seconds. And it works flawlessly!
i believe the 'moveme' sample code by apple shows how to do touch-hold and drag as well. i expect you've already looked at that code and it didnt work for you.
john
__________________
---------------------------------------------------------------------- I love being a dad, flying airplanes and writing code.
----------------------------------------------------------------------
Follow me on Twitter: @BostonMerlin
Feed your brain on Twitter: @iPhoneDev101
----------------------------------------------------------------------
iPhone Apps:
i believe the 'moveme' sample code by apple shows how to do touch-hold and drag as well. i expect you've already looked at that code and it didnt work for you.
john
Yeah, that's not the same as the touch and hold that I needed. The "moveme" sample simply alters the location of a UIView (named "PlacardView") to match location of the current touch. It's not actually a "touch and hold", it just looks like it because you're dragging the image across the screen. In reality though, it's just a location change in the touchesMoved event method.
What I needed is almost like a new touch event method other than began, moved, and ended. I needed an event that occurs after the touch has been held for a duration of time.
Hey, would it be possible to see some full sample code of this being implemented? I'm still a little confused on how to get this working. If you could it would be of loads help to me!
This *should* create a big red UIView rotated landscape style with a UILabel in the top right. As the touch state changes, the UILabel should be updated.... with the added bonus of a custom made touch event "touchHeld" which is a touch state that will occur if you hold your finger on the screen for 3 seconds.
Note: I didn't test to see if this compiles... I just took out the stuff from my app that is related specifically to my app... and copy and pasted the rest in here.
This works unless the code takes time to execute (like an animation), if you touch twice quickly the timer will start a second time before the first one ends.
Thanks everyone for all your past comments and suggestions - I've been reading lots over the last 2 weeks and it has been greatly appreciated.
This touch-timer *seems* like it will be very helpful to me, but being new to Objective-C, I'm stuck.
>>> What part of the code is *linking* the events to a finger touch?
I ask because I want to change that trigger - I need this code to do a couple extra things:
1) Respond by tapping a button, preferably something set up in Interface Builder - not just a blank rectangle on the screen.
2) Display different messages based on how long button is pressed. I think I know how to implement this one, but I cannot begin to figure it out until I have a working button first.
However, after that functionality you'll need to invalidate the timer if it's currently valid and re-add the timer to the run loop.
That might seem odd to do... I mean, the code that's running here is in a method that is called when the timer fires (at which point the timer should not be valid). And why re-add it to the run loop? If you don't, you'll find that your application will lock up when you touch and hold and then move. I'm not sure I understand exactly why myself.
The reason is being when an NSTimer is invalidated, it is released from memory. So when you try to invoke isValid. The code is looking at a nil pointer or memory location and tells you "this method is not available" and crash.
What you should do is retain the NSTimer after you create the NSTimer
Then you don't need to re-add the timer to the loop.
Thank you though for your post. It works like a charm. (with the exception of the repeated timer initialization which as I shown is not necessary)
DjHash
P.S. I wont take credit for this.. I found the solution here.. Re: NSTimer
I hope this helps anyone looking for touches held.
The way I check if touch is held is I declare a UItouch pointer in the header files. When a touch happens, I set the UItouch to the touch that has been passed in.
When touches end, I simply set that to nil.
To find out if the a touch is held down, I check to see if its is valid. It will be valid anytime before the touch is ended
__________________
____________________________________________ Fistpump Nation - The music is hitting hard and you're fighting back. Beat up that beat! Speed Demon - The classic card game Speed, with a modern twist.
Last edited by moonshiner; 03-13-2010 at 11:04 PM.
torynfarr's explanation helped me how to recognize touch. Thanks to torynfarr.
But i want to recognize that a Label is touched. I tried but no luck. Help me in this regard.
torynfarr's explanation helped me how to recognize touch. Thanks to torynfarr.
But i want to recognize that a Label is touched. I tried but no luck. Help me in this regard.
Thanks in advance.
Santosh.
I'm able to recognize when a Label is touched with the following links.
I'm not clear if these extra gesture recognisers only work for iPad, as I'm only in the process of trying them on an iPhone app, but this ought to simplify things if it does...
I'm not clear if these extra gesture recognisers only work for iPad, as I'm only in the process of trying them on an iPhone app, but this ought to simplify things if it does...
It's implemented in 3.2 for iPhone OS. However, the OS for iPhone itself jumped from 3.1 to 4.0, so you can't use it if you are supporting 3.1.