How do I chain two UIGestureRecognizers together? - iphone

What I would like to do is to detect a swipe gesture followed by a pan gesture as part of the same touch sequence. So the user first swipes an object to carry out an action, then, while keeping their finger on the screen, moves up/down to propagate the action to surrounding objects.
I have a swipe gesture recognizer and a pan gesture recognizer.
It seems to me that the ideal way to make them behave the way I want is to do this:
[myPanGestureRecognizer requireGestureRecognizerToSucceed:mySwipeGestureRecognizer];
But although I was sure that I hadn't just imagined requireGestureRecognizerToSucceed:, it seems I have.
Is there a way to achieve what I want without subclassing UIGestureRecognizer?

You can do this by setting both the swipe and the pan to recognize simultaneously, and subclassing the pan so that it does actually mark itself as recognized until the swipe has been recognized.

Related

How do I know that the finger that triggers a touchesBegan is also the same finger that triggers a gesture?

In my case the gesture is a pan. Sample code is appreciated.
UIGestureRecognizer has a property called delaysTouchesBegan. This is YES by default. When turned on, your view won't get -touchesBegan:withEvent: until the gesture recognizer transitions to the failed state. So if you leave that property as YES then any touch you receive in -touchesBegan:withEvent: is guaranteed to not be part of a pending gesture.
If you turn that property off (set it to NO) then you may get -touchesBegan:withEvent:. In this case, if the gesture recognizer subsequently recognizes its gesture, you will receive -touchesCancelled:withEvent: for those touches. This is useful if you need to look like you're responding to the touch immediately, but allow the gesture to then override you (e.g. if the touch turns into a swipe).

Passing a touch gesture

I'm looking for a solution to help "pass" a touch gesture along.
Basically I have a menu, and I want users to be able to drag and drop items from the menu to the canvas in a single continuous drag.
I have already achieved a draggable image via pan gestures (we'll call these instances Sprites). I can also instantiate a Sprite anywhere on the UIView using a button or UIImageView with touch gestures.
However, this currently requires two touches. One to touch down the menu item button and release, creating the Sprite. The second to touch down on the sprite, allowing the user to drag it, and then release it where they want. I would like to merge these touches so that when a user touches a menu item, the Sprite is instantiated and already within the pan gesture, or something to that affect.
I've attached a visual description if that helps. Any help is appreciated. Thanks!
There is no way of artificially forcing UIGestureRecognizer to recognize touches that are passed to a different view.
From the Gesture Recognizer docs:
Delivery of events initially follows the usual path: from operating
system to the application object to the window object representing the
window in which the touches are occurring. But before sending an event
to the hit-tested view, the window object sends it to the gesture
recognizer attached to that view or to any of that view’s subviews.
Figure 3-1 illustrates this general path, with the numbers indicating
the order in which touches are received.
Figure 3-1
Event's delivery happens automaticaly by the system and is delivered to the appropriate view.
To do what you want I would implement the UIGestureRecognizer on the subview (view that contains your UIButton) and on press create an instance of your Sprite object and manipulate that object from withing the gesture recognizer of the subview. Alternatively you could use -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)even to reposition the object yourself.

iOS Touches Began

What I want: Touch a button and a view is added right where the touch is. Without having to lift the finger the touches began/moved automatically begins working on the UIView. So without lifting the finger, I have touched the button and can drag the new view around.
What I don't know how to do:
Stop the touch events on the button and immediately send the touch events to the new view that is directly under the finger.
One option could be to ditch the button and just use the uiview touches to detect when to add the subview you want to let the user drag...
Daniel
As #Daniel suggested ditch the button and just use a UIView, but I believe you may need to have a UIPanGestureRecognizer in place to get your dragging.
You could set a flag when a new UIView is created and then forward any gesture events to that view - only while the user still has their finger down from the initial touch.
After the user has lifted their finger the new view can just deal with gestures by itself by adding a UIPanGestureRecognizer to it.

UIView over another uiview and pass touches through

I have a view sitting over another view. The top view has a UITapGestureRecognizer so I can close the menus (click outside of the menus). But the layer below this needs to receive all the touches.
I can get single finger gestures to pass through, but I can't get the pinch gesture to pass through.
You need to make sure that multiple touches are enabled in both views. That way, a pinch can be recognized! Hope that helps!

How to detect a two finger flick

I want to switch between a couple views with a flick gesture using two fingers. If anyone can tell me what I need to do please help.
Without actually writing the code for you, here's what you'll need to do to track a multi-finger swipe:
First, set your view's multipleTouchEnabled property to YES so that you'll be able to track multiple touches.
In touchesBegan, store the each touches' locationInView property (this is a CGPoint).
Define a "swipe window" that limits the amount of off-axis motion you'll accept and still consider the gesture a swipe. If, for instance, you're looking to track horizontal stripes, perhaps you'd want a "swipe window" of 12x6 -- that is, if your touches move at least 12 horizontal pixels while moving fewer than 6 vertical pixels, you'll consider it a swipe.
In touchesMoved, compare the current location of the touches with the stored starting locations from step 2. If they're still in the "swipe window," do nothing. If one or both of the fingers has moved outside of its "swipe window," then cancel the swipe checking. If they've both met the requirements for a swipe, fire whatever method you want to have called when you've detected a multi-finger swipe.
In 'touchesEnded', stop tracking the swipe, since if the touches have ended but you still haven't fired the swipe method from #4, then they must not have constituted a swipe.
Hope this helps.