I have two questions:
Can I implement gesture recogniser that inherits from UISwipeGestureRecognizer and add logic to the UIEvent handlers?
Can I implement UIGestureRecognizer without attaching it to a UIView? Meaning, I will analyze and manage the UIEvent events and call the proper selector (touchesBegan, touchesMoved, touchesEnded, touchesCancelled)?
In the meantime I have problems reseting the gesture recogniser when the state is UIGestureRecognizerStateEnded.
You asked:
Can I implement gesture recogniser that inherits from UISwipeGestureRecognizer and add logic to the UIEvent handlers?
Yes. See Creating a Custom Gesture Recognizer in the Event Handling Guide for iOS. Also see WWDC 2010 session 121 - Advanced Gesture Recognition. It probably depends upon what you want to do, though, and you should see if you can accomplish what you want by configuring the standard swipe gesture's direction and numberOfTouches parameters. I've done more subclassing on continuous gestures like UIPanGestureRecognizer, but I see no reason why you couldn't do it on a swipe, too.
Can I implement UIGestureRecognizer without attaching it to a UIView? Meaning, I will analyze and manage the UIEvent events and call the proper selector (touchesBegan, touchesMoved, touchesEnded, touchesCancelled)?
No. Obviously you can create one, but it just won't receive any of the events until it's added to a UIView and that view receives touches.
In the meantime I have problems reseting the gesture recogniser when the state is UIGestureRecognizerStateEnded.
You'd have to submit a new question providing a relevant code snippet for us to help you on that one. In general, you'd do any post-gesture cleanup when your handler is called for UIGestureRecognizerStateEnded (and UIGestureRecognizerStateCancelled or UIGestureRecognizerStateFailed) and you'd initialize everything for the next gesture when you receive the next UIGestureRecognizerStateBegan.
Related
I'm trying to pass tap events to the superview but handle longpress events. I've added LongPressGestureRecognizer to the top view but the tap events aren't passed to the superview. I tried multiple approaches:
Overriding hitTest doesn't work since the longpress gesture recognizer handler doesn't get called
isUserInteractionEnabled - same as above
Overriding touchesBegan/Ended and calling them manually on the superview doesn't trigger the tap event
Handing complex tap interactions can be hard, and mixing different approaches can make it much much harder.
Generally, the best way to handle it is to have a single view that has multiple gesture recognisers on them. Implement the UIGestureRecognizerDelegate method gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) and gestureRecognizer(_:shouldRequireFailureOf:) to handle conflicts. When a touch event is recognised it can delegate the action to whatever other object needs to deal with it. Having different views all trying to deal with touches at the same time is not a good way to deal with the problem. Gestures are dependent on other gestures and cannot all be handled independently by different views.
I'm trying to use a swipe gesture along with some logic in touches began/moved/ended. Ideally, it would be good if:
User swipes left/right, touches began/moved/ended logic is not called (or cancelled).
For all other cases, touches began/moved/ended logic is called as usual.
Is this possible?
I tried adding the following (based on process both touch event and gesture recognizer) but touches moved/ended is still called:
leftSwipeGestureRecognizer.delaysTouchesBegan = true
self.leftSwipeGestureRecognizer.cancelsTouchesInView = false
Should be:
self.leftSwipeGestureRecognizer.cancelsTouchesInView = YES
This mean: touches are cancelled in case gesture was recognized, otherwise, touches began/moved/ended called.
From documentation:
When this property is YES (the default) and the receiver recognizes
its gesture, the touches of that gesture that are pending are not
delivered to the view and previously delivered touches are cancelled
through a touchesCancelled:withEvent: message sent to the view. If a
gesture recognizer doesn’t recognize its gesture or if the value of
this property is NO, the view receives all touches in the multi-touch
sequence.
In this case I would create a custom UIGestureRecognizer for a new behaviour in touches began/moved/ended. Useful link here. Than I would set delegate for both swipe and custome recognizers and implement gestureRecognizer:shouldRequireFailureOfGestureRecognizer: method to fulfill requirements. Link to documentation.
Hi any one can explain me, what are the cases can i use the following UIGestureRecognizer Methods.
1. - (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer*)preventingGestureRecognizer
- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer
2. - (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer
3. - (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer
- (BOOL)shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer
Kindly give the use case of all this three methods, if u have any example kindly comment here.
Thanks in advance.
Please read the Apple's Documentation.
canBePreventedByGestureRecognizer:
Overridden to indicate that the specified gesture recognizer can prevent the receiver from recognizing a gesture.
canPreventGestureRecognizer:
Overridden to indicate that the receiver can prevent the specified gesture recognizer from recognizing its gesture.
requireGestureRecognizerToFail:
Creates a dependency relationship between the receiver and another gesture recognizer.
shouldBeRequiredToFailByGestureRecognizer:
Overridden to indicate that the receiver should be required to fail by the specified gesture recognizer.
shouldRequireFailureOfGestureRecognizer:
Overridden to indicate that the receiver requires the specified gesture recognizer to fail.
All those methods simply establish dependancies of different types between different recognizers. Certain gesture recognizers may use similar gestures, and these are typically set up so that one takes precedence over another.
For example, a scrolling gesture and a swipe gesture are similar in that they both involve a touch moving in a particular direction, so you might set up the swipe recognizer such that it requires the scrolling recognizer to fail before the swipe can be recognized. Or, you could set them up so that the scrolling recognizer prevents the swipe recognizer from being activated while the user is scrolling.
Is it possible to setup UITapGestureRecogniser for touch down event? Default is touch up...
No, that's not possible, but it shouldn't be hard to subclass UIGestureRecognizer to create your own recognizer that does that.
You could also use a UILongPressGestureRecognizer with the minimumPressDuration property set to 0.0. Note however that your action will then be called continuously when the touch moves, so make sure to check that the state of the recognizer is UIGestureRecognizerStateBegan in the action (this will only be once).
A tap gesture recogniser detects a tap. This is different from touch up.
The best way to detect a touch down is to write your own touchesBegan method in the custom UIView or UIViewController.
I have a project that I started out using a tap gesture recognizer for. I realized I didn't have enough control with the tap gesture recognizer, so I've started coding with using my viewcontroller as a UIGestureRecognizerDelegate. Just to make sure I was on the right track, I added methods for touchesBegan, touchesMoved, touchesEnded, touchesCancelled. The methods are empty except for NSLog calls so I can tell what is being fired when I try different things.
Things worked as expected except that I was getting a bunch of calls to touchesCancelled. I assume this is because of the tap gesture recognizer I still have in place. I'm not ready to remove the tap gesture recognizer, so I just wanted to confirm that this is what would happen if a gesture I used was actually a tap.
The documentation says:
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.
But I suspect my scenario just outlined is just as likely. Am I correct?