When to use IBAction vs. UITapGestureRecognizer? - swift

I have seen storyboard buttons combined with IBAction code as well as UITapGestureRecognizers (not speaking here of programtically defined buttons).
I am curious if there is any (not strongly opinionated) reason to prefer one over the other in specific situations.

Buttons have their own tap action events.
All other UI elements have no.
E.g., if you want to handle label tap event you have to use gesture recognizers.

UIButtons have actions. you don't need tap gesture for it. You may need tap gesture for UILabel or UIView.

Related

Is it possible to add a custom gesture recognizer to a view in TVOS app?

In my TVOS app I created a custom gesture recognizer, which is a subclass of a UIGestureRecognizer.
Later in the code I'm trying to add it to a collection view cell.
let customGest:CustomGestureRecognizer = CustomGestureRecognizer(target: self, action: Selector("myMethod:"))
cell.addGestureRecognizer(customGest)
in the debugger I see that my gesture recognizer is getting initialized properly. However, none of it's touches methods are getting called (touchesBegan, touchesMoved..).
I've done this in iOS just fine, so I'm curious if it is possible to do so in TVOS?
Any kind of help is highly appreciated.
Touch events (UITouch) and button press events (UIPress) are first delivered to the focused view, and then they go up the responder chain from there. So your custom gesture recognizer will only fire if the cell you added it to is focused, or if the cell contains the focused view as a descendant.
Is the cell you're adding this gesture to focused (or contain the focused view)?

How can I highlight the BarButton in navigation bar without tapping it?

Typically, the UIBarButtonItem will be highlighted when we tap it.
However, I intend to show the users that the action is automatically done for them when the view is loaded after 4 sec.
So I want to highlight the Button without tapping it.
How can I achieve that?
For a UIVIew object such as a UIButton, you can either use the following code Glow category on UIView that adds support for making views glow or use this example.
If you are using the first one, you can just call startGlowing and stopGlowing. When you call startGlowing, the view will start to pulse with a soft light, this effect is removed when stopGlowing is called. Check this.
For UIBarButtonItem, you might have to use the solution provided here.

UITableview didSelectRowAtIndexPath supercedes double tap gesture by UITapGestureRecognizer

I've set up a UITableView with a double-tap UITapGestureRecognizer. But attempts to double-tap a cell by the user just launches didSelectRowAtIndexPath twice. Are these two supposed to work together?
(i'm aware i could use a single tap gesture recognizer in place of the built-in behavior of didSelectRowAtIndexPath, but here's the problem with that: the cell also has a button that I can't press anymore when i add the single tap gesture recognizer. Also, I've seen examples on SO of users building double tap functionality into didSelectRowAtIndexPath, but isn't that a bit too much of a hack?)
More info about Kris' answer:
cancelsTouchesInView
delaysTouchesBegan
delaysTouchesEnded
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIGestureRecognizer_Class/Reference/Reference.html
In my case I had a problem when adding 2 tap gestures to a UIImageView that was on a custom UITableViewCell. What happened was the didSelectRowAtIndexPath: was called when you tap/double tap on the UIImageView. When I had only one tap gesture, the didSelectRowAtIndexPath: was not called (and for me, that was the right behavior.
To prevent the didSelectRowAtIndexPath: from being called when using two tap gestures (single/double tap), I added this code to the first tap gesture (the single one):
tapGesture.cancelsTouchesInView = YES;
tapGesture.delaysTouchesBegan = YES;
After this change, a tap/double on the UIImageView (on top of the custom cell) did not trigger the didSelectRowAtIndexPath:
Looks like I can get didSelectRowAtIndexPath and the double tap gesture recognizer to play together nicely using the delaysTouchesBegan and cancelsTouchesInView properties of the gesture recognizer.
The other option described by #MSgambel seems to work equally well.
You can use a single-tap gesture recognizer in place of didSelectRowAtIndexPath, even if there is a button in the cell. You just need to check if the touch location is inside the UIButton's view or not in order to handle both cases. Hope that Helps!
I tested the "delayTouchesBegan" method with double taps but I found that the single tap received by the table is then delayed, making the table interaction less responsive to the user, and perhaps annoying.
My solution is a bit pedestrian but I use a timer to detect taps in method didSelectRowAtIndexPath. I record the tap count of "1" for the first tap, and if the user does not tap again with 0.2 seconds it displays the item selected. If the user tapped within 0.2 seconds for tap count "2" then I display another item (an action sheet). I reset the tap count each time.
This method uses more code, but provides quick response from the interface and the user does not need to know what is happening behind the scenes - just that the UI is responsive.

can implement UITapGestureRecognizer with array of image view?

UITapGestureRecognizer can implement with array of image? can it work same as single image?
how it work?
It works on a single view. You will have to use a single recognizer per view.
You can however use the same target-action pair to handle all the gesture recognizers. If you are looking for the gesture to behave the same way for all the image views then this is the easiest thing to do. If the action must identify the view and handle it appropriately, you can use the view property to complete the appropriate action.
If you are looking for how gesture recognizers work, read this.

How to disable multitouch when having several views?

I created my own custom view that extends UIControl. This custom view has its own touch implementation. I implemented touchesBegan, Moved, Ended, and Canceled methods in it.
In the main view controller, I created several instances of this view. So in the screen, there are a number of custom buttons.
I want to disable multitouch in my app. If I click one custom button, then other buttons shouldn't respond.
Actually, it was easy to implement this. While I held some buttons, I could just make other buttons' userInteractionEnabled property to NO until I ended touch.
But the problem is that when I tap these several buttons at the same time, two or more touchesBegan methods work simultaneously, and message passing is messed up.
I tried to set multiTouchEnabled = NO and exclusiveTouch = YES, but it still didn't work.
How can I force to disable multitouch in my app?
Thank you.
You need to set exclusiveTouch to YES, not NO (which is the default anyways). The name of the property refers to the view being the exclusive recipient of any touch events for the duration.