iPhone - Detecting touches and canceling them? - ios

I am dtecting touches on my UIView.
Is some situations I want to be abel to cancel touches so that touchesEnded won't get called. But doesn't matter what touchesEnded will always get called?
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if (SOMETHING_SPECIAL)
{
[super touchesCancelled:touches withEvent:event];
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
//I don't want it to get here if touches were canceled how can i do this?
}
- In my touchesEnded how can I determine whether touches were canceled or not?

TouchesEnded will always get called wherever your touches where canceled or not, so I would suggest instead having that exact:
if (SOMETHING_SPECIAL)
{
}
In your:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

To get the touchesCancelled event, implement this method from UIResponder.
touchesCancelled:withEvent:.

Related

iOS delay touchUpInside button event

I have some custom animations in my UIButton subclass. I override some inner methods for starting and ending animation
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
//there is my start animation
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
//there is my end animation
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesCancelled:touches withEvent:event];
//there is my end animation
}
There is almost all good. All my buttons make some actions on event UIControlEventTouchUpInside. And there is my problem. Methods touchesEnded and touchesCancelled are called only after my app handle UIControlEventTouchUpInside event. So animations in button looks not so nice like I want.
So question is: can I delay UIControlEventTouchUpInside event on some ms and firstly handle touchesEnded method of my button for smooth animation?

How to get the position of the current touch?

I'm building a game that basically the goal is to hold a button pressed for a long time.
The game starts with the "touchesBegan" call, and ends on "touchesEnded".
I have a issue that some very specific times this call, is not called. After a some search i figured out i'm not the only one with this problem :
https://discussions.apple.com/thread/1507669?tstart=0
There is a known problem that some times "touchesEnded" is not called.
So the work around i was thinking of doing, is setting a timer, and checking every once in a while, if there is a finger pressing, and where exactly on the screen.
Problem is, i know only about these methods:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
And nun of them serve me for this use.
Is there a way of getting the current touch on screen?
Thanks
touchesCancelled:withEvent:
When a touch begins, touchesBegan:withEvent: is called. After that, at some point in the future, either touchesEnded:withEvent: or touchesCancelled:withEvent: will be called! You can, e.g. create a method touchesEndedOrCancelled:withEvent: and call that method from both touchesEnded and touchesCancelled.
To get the current touches you need to keep track of them on your own. Just create a mutable set _allTouches
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[_allTouches unionSet:touches];
// ...
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[_allTouches minusSet:touches];
// ...
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[_allTouches minusSet:touches];
// ...
}

Programmatically initiate hitTest:WithEvent after gesture recognizer was canceled and return a different UIView to respond to events

I am overriding hitTest:withEvent to return self (the bottom most view)-
When returning self - my view will respond to touch events in turn initiating gesture recognizers.
If a gesture is canceled or some set of conditions happened - I want to manually initiate hitTest:withEvent and then return a different view to take care of the same sequence of events/touches that occurred. This is necessary as a gesture recognizer only initiates after hitTest:withEvent returns the gestures view and its state changed to began.
I am not sure how to do this - I thought about manually calling on my subviews
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
}
But I don't have the event parameter (The gesture received it)
I think this could not be done, pass touch event to UIGestureRecognizer is private API. But you can pass touch event the bottom most view received to any view you like and do your own gesture recognize.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UIView* selectView = [self _findMatchView];
// maybe convert touches to selectView coordinate
[selectView handleTouchBegan:touches withEvent:event];
}

iOS: UIVIew touches delegates vs single tap recognizer

I am handling Touches delegates and UITapGestureRecognizer for single tap. Following are the methods. When I single tap on my View, I get three events in order of TouchesBegan, SingleTap, and TouchesEnded. Is there anyway to stop TouchesEnded event when I have SingleTap detected? Basicaaly I don't want to perform tasks in TouchesEnded if TouchesMoved didn't happen. I have done this using failTouchEnded BOOL variable in SingleTap and checking it in TouchesEnded but not sure if it is a good idea!
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
failTouchEnded = NO;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if(failTouchEnded) return;
}
- (void)GestureView:(GestureView*)view handleSignleTap:(UITapGestureRecognizer*)recognizer {
failTouchEnded = YES;
}
gestureRecognizer has a property cancelsTouchesInView. if it is YES (which is default) cancels the touches if the gesture recognizer recognizes the gesture. So you will get a touches canceled instead of touches ended. You should set delaysTouchesEnded to YES too if it is not YES

iOS 5.0 sendEvent called two [2] times

I subclassed the UIWindow, but for some reason the - (void)sendEvent:(UIEvent *)event gets called 2 times for any interaction with the screen. Any ideas why would that happen?
For debugging purposes, subclass window (of app delegate) and override sendEvent: method
-(void) sendEvent:(UIEvent *)event
{
NSLog(#"%#",event);
[super sendEvent:event];
}
Most probably, you will notice the events responsible for TouchesBegan and TouchesEnded (for tapping). This can be tested by subclassing the View and overriding touch related methods.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"tocuhesBegan");
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touchesMoved");
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touchesEnded");
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touchesCancelled");
}
Also, try drag/swipe on the view to notice the change in count of events sent to view :)
sendEvent gets called for fingerDown and allFingersUp

Resources