Handling touchesBegan in UITableViewCell disables didSelectRowAtIndexPath - iphone

I'm implementing swipe gestures in my customtableviewcell control and so I hvae to implement touchesBegan event.
I'm able to implement the swipes, but unfortunately, because the touchesBegan gets handled in the customcell, i'm not getting a didSelectRowAtIndexPath message on the tablecontroller. If the touchesBegan method is disabled, it works.
How should this be handled? I want the touch event to bubble up the responder chain after the touchesBegan is processed. How can I do this?
Thanks.

I"m sure you can see that this is happening because you are overriding a method that was previously defined on a super class. and by doing so means that the events are not being called.
have you tried calling [super touchesBegan]? that way all upstream stuff is handled. and you can override the swipe gesture.
or another option is to call the delegate when the touch is detected in your own touches method.
something like (you will probably have implementations of the other touch events as well)
-(void) touchesBegan
{
//logic to detect tap only.
[tablecell.delegate didSelectRowAtIndexPath:(some way to determin touched row)]
}

Related

How to prioritize gesture recognizers and touches in a UIView

From reading the UIGestureRecognizer Class Reference it is implied that the API will handle the prioritizing of touches and gesture controls for you, making sure that your touchesBegan and related methods are not called on the view unless the gesture recognizers have first failed:
A window delivers touch events to a gesture recognizer before it delivers them to the hit-tested view attached to the gesture recognizer. Generally, if a gesture recognizer analyzes the stream of touches in a multi-touch sequence and does not recognize its gesture, the view receives the full complement of touches. If a gesture recognizer recognizes its gesture, the remaining touches for the view are cancelled.
I have added a swipe gesture to my view, and it is working. Via some logging, when I do a single swipe, the method reports as such. However, my touchesBegan method is also reporting via its log, despite that the touchesCancelled method is, as expected, also receiving a message.
I want, and expect, the gesture recognize to prevent touchesBegan or touchesMoved from being called.
So my question is: for the gesture recognizer to in fact delay touches based on its state, is there additional setup necessary? The docs do not suggest anything else as necessary.
My setup is simply:
swipeUpTwoFinger=[[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(doubleSwipeUp:)]autorelease];
swipeUpTwoFinger.direction=UISwipeGestureRecognizerDirectionUp;
swipeUpTwoFinger.numberOfTouchesRequired=2;
[self addGestureRecognizer:swipeUpTwoFinger];
I have also tried this test to make sure a recognizer has failed before processing with touchesBegan (this test should not be necessary if you believe what the docs say above) but the touchesBegan is still processing the log line after this test:
if (swipeUpTwoFinger.state==UIGestureRecognizerStateFailed)
It sounds like you need:
swipeUpTwoFinger.delaysTouchesBegan = YES;

willSelectRowAtIndexPath, didSelectRowAtIndexPath are not calling in iphone when using touches began method and performselector

I am developing an application, in which one of the screen i am using have tableview, it is tableview controller. i have written custom touchesbegan,touchesmoved,touchesended methods insside a tableview controller class, when ever user presses on any cell touchesbegan method is calling and withing this to detect long tap what i did was
[self performSelector:#selector(longTap) withObject:nil afterDelay:1.0];
if user removes his finger before 1sec, in touchesmoved and touchesended methods i am canceling the performselector.
now what happens is when i press & hold for 1min longTap method is calling and willSelectRowAtIndexPath, didselectRowAtIndexPath are not calling. but i need to get the indexpath.row value before performing any action on longTap method.
Can any one help me on this issue. please share your valuable suggestions.
Thanks in advance.
You should consider using a gesture recognizer like UILongPressGestureRecognizer. Fiddling with the touch events yourself is hard and error prone.
It is very easy to break a flow of events that UIKit classes depends upon to function. Gesture recognizers is the public API for hooking into the touch event flow, in simple and advanced easy, without breaking UIKit functionality.

When touches Cancelled method get invoked in iPhone?

I am able to understand that when user just touches the view, touches Began and Ended called. When user swipes their hand on a view, touches Moved method gets called. But when does touches Cancelled get called or by what action on user this method gets called?
I think probably the most common reason for touchesCancelled being called (since iOS 3.2 anyway) is following the recognition of a gesture by a UIGestureRecognizer. If your view has any kind of gesture recognizer attached to it then it is often very important to provide a custom implementation of the touchesCancelled method - note this includes ready made views that use gesture recognizers, including UIScrollView.
By default, gesture recognizers cancel the delivery of touches to the hit-test view upon recognition, although this behaviour can be disabled. This involves sending the touchesCancelled message to that view, most likely following a touchesBegan or touchesMoved message. If your touch handling code is relying on code implemented in the touchesEnded method, it is possible this may never be fired and some kind of serious problem could occur, hence the need to properly tie up any loose ends in touchesCancelled.
The ins and outs of gesture recognizer functionality is obviously a bit more complex than I've mentioned here - I would thoroughly recommend reading Apple's Gesture Recognizers documentation.
Also, check out the WWDC videos on gesture recognizers (starting from 2010).
Note: touches also get cancelled if you start a UIView animation after touchesBegan. To prevent this make sure you include UIViewAnimationOptionAllowUserInteraction:
e.g.
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
self.aView.hidden = NO;
self.aView.alpha = 1;
} completion:nil];
From the Apple Reference documents
Sent to the receiver when a system
event (such as a low-memory warning)
cancels a touch event.
Discussion
This method is invoked when the Cocoa
Touch framework receives a system
interruption requiring cancellation of
the touch event; for this, it
generates a UITouch object with a
phase of UITouchPhaseCancel. The
interruption is something that might
cause the application to be no longer
active or the view to be removed from
the window
When an object receives a
touchesCancelled:withEvent: message it
should clean up any state information
that was established in its
touchesBegan:withEvent:
implementation.
The default implementation of this
method does nothing. However immediate
UIKit subclasses of UIResponder,
particularly UIView, forward the
message up the responder chain.
And, from the Event Handling Guide for iOS, p. 19:
It sends the touchesCancelled:withEvent: message when the touch sequence is cancelled by a system event, such as an incoming phone call.
I was handling touchesBegan()/touchesMoved() on a view under UIScrollView, which is challenging. My touches kept cancelled by somewhere when I pinch (somehow it is OK with single touch movement), I was investigating how to stop being cancelled. I figured out, that there is a property Can Cancel On Scroll on UIScrollView, and you may check it off to stop being cancelled, if your case is similar to my case.
It sounds there are many cases where your touches are being cancelled, so my answer is just one of them.

ObjC Button Released Touch Up Outside

I have a button, when held down motion occurs, when released it should stop. I know I could write two methods, one to start and one to stop motion, I was wondering if in the one method I could detect both based on Touch Up Outside vs. Touch Up Inside.
If Touch Up Outside do this if Inside do this.
-(IBAction) startMotion: (id)sender {
NSLog(#"Forward or back button is being pressed.");
UIButton * buttonName = (UIButton *) sender;
NSLog(#"Button Name: %#", buttonName.currentTitle);
}
Yes, you could write one method and link the IBAction "touchUpInside" and "touchUpOutside" to the same IBAction member function - via Interface Builder.
The only downside would be that you would not be able to tell if it was a touchUp inside or outside when it was called. (It doesn't sound like this matters to you.)
If the later was an issue, you could alternately implement independent touchUpInside and touchUpOutside methods which in turn call the same method - a third custom one - into which you could pass an "inside" or "outside" flag from the proper IBAction handler.
Touch up Outside won't give you the functionality you're looking for, I don't think. The person would have to move their finger outside the boundaries of the button and then lift remove the finger
Why not use touchdown to initiate the motion and touch up inside to stop it?

Does UITextField consume touch events?

My view controller has UITextField object as a subview. The controller is set as target to handle the text field's UIControlEventTouchUpOutside event.
I'm trying to use this event handler for dismissing keyboard when the text field becomes first responder, but it seems to be never called. Delegate methods like textFieldShouldReturn work just fine.
Why the text field object doesn't send action message to the target? I tried this scheme for bunch of all touch events, but no luck.. Or do I have to subclass UITextField somehow to be able to catch this event?
Thanks in advance!
UITextField for sure responds to those event to handle cursor positioning and so on. It might not 'forward' those event to its parent. If you need to intercept those, you can subclass UITextEvent and catch those event yourself (of course do not forget to call [super blablabla] in order to keep the standard behavior.
Maybe It just doesn't respond the UIControlEventTouchUpOutside event. I am sure it will respond UIControlEventValueChanged event. I think you can put a transparent custom UIButtom as background view, and if any touchInSideUp in the UIButtom, you can dismissing keyboard as desired.
It responds to the same events as UIButton. Take a look in IB. Also you may consider using UITextFieldDelegate method
- (BOOL) textFieldShouldBeginEditing:(UITextField *)textField