iOS: Several Touch Event on View Controller? - ios

I have developped a small application with 2 View .
My first UIView is a Menu containing some images. When I click on one of them, I switch on the Second UIView to display it.
Afterwards, I created a new UIView who is a "menu extension" of my first Menu. I created a UIView but when I put the component "Swipe", the application do not switch to my second new menu.
I would like to know, if Iphone App supports several touch event on the UIView ?

Objects of class UIGestureRecognizer are attached to a UIView object, not to UIViewController objects. And it is possible to attach multiple gesture recognizers to a single view, see its gestureRecognizers property.
But you have to be careful: If you want a swipe to be recognized, a single tap recognizer might fire before the swipe could be recognized, since the latter requires the move of the finger. Therefore, you can configure multiple gesture recognizers of the same view such that they show the required behavior, e.g. that a single tap recognizer fires only when a swipe recognizer does not fire, etc., see the docs of UIGestureRecognizer Class Reference.

Related

Propagating specific touch event to view underneath

I want to implement a feature similar to this:
View A and View B are all child views of the same parent UIView. View A and View B are sibling views. View A is the same frame size as the parent view. View B is only half of the size and it's above View A. I want to capture swipe events/gestures on View B, but still propagate other events/gestures (e.g. Tap) from View B to View A. So user can still interact with View A (e.g. tap on the button on View A) while View B is only capturing swipe gestures.
I have tried implementing following methods on View B
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
but seems like it's all or nothing approach. as I cannot detect in these methods if the event is a tap or a swipe. And I didn't find any API which can programatically trigger a tap on a UIView (not calling touch related methods).
You should move your rear sibling view to be a subview of the front view as this effective looks the same but makes the UIResponder chain behave correctly. UIGestureRecognizer can then do the rest of the work for you. Specifically it has a property, CancelsTocuhesInViews that you can turn off so it doesn't eat touch events and it has a delegate with methods that can allow you to specify the conditions under which a UIGestureRegonizer should fire. Implement the UIGestureRecognizerDelegate methods that you want to make your logic work. For instance if you want the overlay view to handle a tap only if a bunch of other gestureRecognizers don't handle the tap first then you implement gestureRecognizer(_:shouldRequireFailureOf:) and have it return true for every other gesture recognizer you want to go first; your gesture recognizer will then only fire when all of these other gesture recognizers have failed to handle the tap.
If I understand you correctly, what you want to do is usually done using UIGestureRecognizer objects and its subclasses. You can make one gesture recognizer (i.e. a swipe (or was it pan?) gesture recognizer) depend on another one (one for taps).
You can tell one gesture recognizer to only trigger when another has failed to detect its gesture. I haven't had to do that yet, so can't give you more detail, but I'd look into those classes and see if there's a way to chain them so it handles a swipe, and just does not handle taps. If you don't handle a tap, it should automatically go to any subview that will handle it, I think.

How to override gesture recognizer on UIButton to allow tap events to bubble to superview?

CustomButton, a subclass of UIButton, is embedded in CustomView, which is a UIView subclass.
Tap events on CustomButton do not bubble to CustomView, because per the Apple docs:
In iOS 6.0 and later, default control actions prevent overlapping
gesture recognizer behavior. For example, the default action for a
button is a single tap. If you have a single tap gesture recognizer
attached to a button’s parent view, and the user taps the button, then
the button’s action method receives the touch event instead of the
gesture recognizer.
and:
If you have a custom subclass of one of these controls and you want to
change the default action, attach a gesture recognizer directly to the
control instead of to the parent view. Then, the gesture recognizer
receives the touch event first. As always, be sure to read the iOS
Human Interface Guidelines to ensure that your app offers an intuitive
user experience, especially when overriding the default behavior of a
standard control.
1) But if you attach a new tap gesture recognizer, doesn't this create two recognizers: the default and your custom one?
2) How do you override the default one and leverage its native functionality (e.g., highlighting button on touch) instead of creating an independent recognizer?
3) What's the right way to override the tap gesture for a UIButton subclass such that tap events bubble to the superview?
Most appreciated if examples were given in Swift.

Forwarding touches to UINavigationController Interactive Pop Gesture Not completely Working

I'm trying to enable interactive pop gesture recogniser on my keyboard's accessory view. It does not work by default.
I passed an interactive pop gesture recogniser reference to my accessory view in order to forward its touch events to the recogniser
It particularly works: the navigation bar's title gets changed and the background of the accessory view reveals the previous view controller's view as if the transition did start. But the top view itself remains in place even if the gesture recogniser completes tracking.
I also tried to forward touch events to the navigation controller itself, to its view, to its top view controller and to their window. Nothing changed even after forwarding to all of them simultaneously
Any ideas what is missing?
It looks like it is not possible to reuse touch event instances in the responder chain. Once the sendEvent: on UIWindow is called, there is already a certain view owning the touch, so there is no cense in forwarding the UIEvent instances to other views or their gesture recognisers.
However, the owning view can forward events to its nextResponder()s (e.g.: one of the gesture recognisers attached to this view or to one of the subviews of the view)
The only chance to forward touches to another view (from another view hierarchy) or another view's gesture recognisers is before the UITouch object creation: i.e. on the UIWindow level during the hitTest:withEvent: method invocation, which calls the pointInside:withEvent: method
Anyway I'm not sure whether it is possible to forward touches from one UIWindow to another. Will update the answer later
http://www.russbishop.net/uitouchtypestylus?utm_campaign=iOS%2BDev%2BWeekly&utm_medium=email&utm_source=iOS_Dev_Weekly_Issue_225
http://smnh.me/hit-testing-in-ios/

In iOS 8 what is the correct way to add a gesture recognizer on everything in my view controller except a button, without adding an additional button?

I have a button that when tapped shows the button text. In iOS 8 what is the correct way to implement a gesture recognizer to my view controller, so that when anything else is tapped besides that button will remove that text. I would like to avoid adding an additional button because I have multiple buttons that I would like to apply this gesture recognizer to in addition.
You could try using touchesBegan - that would capture touches elsewhere, however if you have another UI element in the view that interacts with touch I believe touchesBegan will not be called in that case as the UI element will not pass the touch event on.
Implement it and pop some logging in there and see what's going on. Could be the solution you're after.

How to detect touch on screen in custom UIView?

I want to watch in my UIView subclass for user touches on the screen. Especially there are some additional conditions:
the touch should not be catch by my view (for example, if user taps some button or scrolls something that action should be accepted)
there can be multiple views which are watching for touch and they should not conflict with each other
the approach should be as general as possible (so we can catch taps on tabbar or navigation buttons)
I can suppose to add specific fullscreen view with customized hitTest: method. This view has interface to add/remove delegates for watching for touches. But this method is "hard" in coding terms and I would like to find more elegant and simpler solution.
you can write touchesBegan in that UIView subclass.
Because if it had any subview like button or scrollView, they would be first responders ,and touches on scrollView wont fire touchesBegan of your UIView subclass.
And it wont conflict with other touch listeners unless the listener subView is explicitly passing that touch to your Subclass.

Resources