How to pass to let a subview UIButton get the press event? - ios

I have a view with a tap gesture and a UIButton on it with its corresponding action.
The problem is that If I press the button its corresponding action is not getting called instead the tap handler is getting called.
I did a hitTest and stopped the gesture-handler from doing anything if the hit was on the button.
But I am unable to let the button's action do something.

You can set your controller class to be the delegate of the UIGestureRecognizer and then implement this method:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return [[touch view] isEqual:UIViewThatIsNotYourButton];
}
Your hitTest method should actually achieve this, so you might also check if the UIButton is really getting an action assigned to it.

Related

How to avoid to trigger a UIPanGestureRecognizer when there is a tap on a UIButton?

I have added UIPanGestureRecognizer on the view of my UIViewController.
In this view (a calculator) are some UIButton triggered by the event .TouchUpInside.
The problem comes if I tap on the button and make a small pan at the same time (which might happen if you tap quickly a button and are moving to the next one at the same time). Then the pan gesture is triggered. I would like to avoid it when there is a tap on a button. But I would like to allow it if the tap takes too long (let say 0.3s is enough to trigger the pan gesture).
How can I achieve that?
Set the property cancelsTouchesInView of your gesture recognizer to NO.
Then your button should work properly.
You can use the delegate method like this-
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
if ([touch.view isKindOfClass:[UIButton class]]) {
return NO;
}
return YES;
}
There is a dirty solution. You can just grab it in a UIScrollView

How to prevent UIView passing touch events to UIView's superview?

I have a UIViewController object (bottomViewController) in the window, and a UIView object (upperView) on the UIViewController.There are some buttons (buttonOne, buttonTwo, buttonThree) on the UIView. The bottomViewController have a UIGestureRecognizer.
Now, I have a touch event on the upperView; the touch point is outside of the buttons. The upperView will pass the event to its superview (bottomViewController).
How can I prevent upperView from passing the event - to which it can't respond - to its superview?
Make use of:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
int the UIGestureRecognizerDelegate
return YES if you should receive touch NO if not, based on what ever logic you want to apply. You have the UITouch and UIGestureRecognizer which both contain lots of useful information.
Remember to set delegate of UIGestureRecognizer to self.
You could assign tags to views and then check for if condition and put up logic into it.

Cancel touch on UIButton on touch move (iOS)

I have a view with button and touch-move gesture. When user touches button it becomes selected and keeps receiving touch-move events. I want to deselect the button on touch-move and pass moves to gesture.
How to cancel touch receiving on button "elegantly"?
Try the next line of code on Swift 4
youButton.touchesCancelled([], with: nil)
Works well with pan gesture reco
You need to implement the UIGestureRecognizerDelegate. Specifically this method. Then just build your logic for deciding if the gesture should receive the touch or not. If you return NO then the touch is up for grabs for the button. if you return YES the gesture to take the touch.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
If you never even more control I think you'll need to subclass the button and takeover its hit testing.

IBAction UIButton firing is delayed

I have a UIButton connected to an IBAction in Interface Builder.
The Problem:
The action firing and the de-highlight of the button both take a little bit to happen.
The Facts:
View structure:
View
10 Buttons (connected via UIControlEventTouchUpInside to the IBAction
View (Subview)
Gesture recognizer
Text Field
The Subview has a UITapGestureRecognizer, which delaysTouchesBegan and delaysTouchesEnded both are set to NO
The action is happening in the main thread.
Testing a simple button (with no images or title, and only a simple NSLog), the result is the same
The Question:
Why are firing and the de-highlight delayed?
In the end, I added somewhere some UIGestureRecognizer, and forgot to set delaysTouchesBegan to NO =(
Ok I think that because of the UITapGestureRecognizer .. try to do the following :
connect an IBOutlet to your button.
2.assing the UITapGestureRecognizer delegate to your ViewController.
3.Implement this gesture delegate method in yourViewController
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch {
return (! [yourButton pointInside:[touch locationInView:yourButton] withEvent:nil]);
}
This will make the tap to be recognized to your button not to the recognizer.
Make sure your touch event is set the first contact of the button which would be the touch down event otherwise there will be a delay in the action until whichever other event you chose gets completed (i.e. touch up inside, touch up outside, etc).
In my case, there was a delay on IBAction for a button that was in a custom CalloutView of an MKAnnotationView.
In the same way there is a ~0.5sec delay between pressing the MKAnnotationView and the MKAnnotationView actually being selected, there is also a delay between any other user interactions you might add as a subview of the MKAnnotationView.
The solution is to disable the native UIGestureRecognizer within MapView that is causing the delay of any MKAnnotation view selections.
This can be done with the solution on this post:
Set isZoomEnabled = false within a gesture recognizer attached to the mapview on any tap, then set isZoomEnabled = false within a 0.5sec async dispatch.

Two UIGestureRecognizers and UIButton

I encountered this problem and was able to resolve it as described.
Gesture recognizer and button actions
But when I added a second UIGestureRecognizer to the same UIView the UIButton selector is not called for the second UIGestureRecognizer, only the first.
So I have a single UIView with two UIGestureRecognizers. There is a UIButton on the UIView.
The UIButton selector always get called correctly after the first UIGestureRecognizer. The first touch on the UIButton for the second UIGestureRecognizer does nothing, but the second touch on the UIButton works as expected.
If I remove the first UIGestureRecognizer from the view then the first UIButton press fires the selector as expected after the second gesture is performed.
Any idea why the first touch on the UIButton doesn't fire the selector but the second does?
try to put his delegate method in your viewController
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
returning YES to this method is guaranteed to allow simultaneous recognition.

Resources