selector is not called 2 tapgesture - ios

I have added a UITapGestureRecognizer to a view, but when I click it the method is not being called.
func addTapGestuere(uiview: UIView) {
let tapGestureRecognizer:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: Selector("cardTapped:"))
uiview.addGestureRecognizer(tapGestureRecognizer)
}
I run this on the viewDidload
self.addTapGestuere(self.Card1View)
self.addTapGestuere(self.Card2View)
I put a break point on the method
cardTapped(recognizer: UITapGestureRecognizer) {
}
but when I click on the image the method isnt called. I have user interaction enabled for all the views.

Be careful about the following:
The UIView you are trying to add the UITapGestureRecognizer has userInteractionEnabled set to true:
self.view.userInteractionEnabled = true
The UIView you are trying to get the tap to has no other views covering it. Use the View Debugger to confirm this.
Most importantly, make sure you are adding the UITapGestureRecognizer to the correct UIView. Adding it to self.view will add it to the UIViewController's view.
As a side note: You can add the UITapGestureRecognizer using the Inetrface Builder itself, then connecting IBAction for the same. Will reduce the probability of simple mistakes.

Related

iOS11 UIBarButtonItem action not get called

I used Xcode9 Beta6 to build the project, the action was called correctly on iOS10 device, however it is not work on iOS11 device.
In My project, there are some viewControllers have a UIToolBar on the top, and the toolBar contains some UIBarButtonItems.
There is one this kind of viewController, whose UIBarButtonItem action is not called when I tap the UIBarButtonItem. I can see the tapping animation (the icon become dim first and back to normal after finger released)
At the end of viewDidLoad, I print the info of toolbar.items to indicate that target action are set properly.
Debug Output
In my case I was setting up the button and instantiating it as a property of the vc
class myVC: UIViewController {
let closeBarButtonItem = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(close(_:)))
}
If I moved this to ViewDidLoad it resolved the problem
class myVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let closeBarButtonItem = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(close(_:)))
}
}
I solved this problem by removing a current gesture recognizer from my view and adding a new one. Than I opened the connections inspector of my view and add gestureRecognizer connection to my gesture recognizer.
Apple has confirmed this bug.
My temporary solution is changing the gesture recognizer area by removing the overlap area, so that the tap gesture won't block the tap event on UIBarButtonItem.
It is happening only for iOS 11 and when custom UIView used for rightBarButtonItem (or left also). If you are using UIBarButtonItem then it will work fine.
There is 0 width of this custom bar item, so we need to set it to something.
In viewDidLoad of this controller you can add code, you can replace 100 to something what will work for you:
if let view = self.navigationItem.rightBarButtonItem?.customView {
view.widthAnchor.constraint(equalToConstant: 100).isActive = true
}
At least as an easy temporary solution it is fine.
In my case the problem was a gestureRecognizer added to the whole main view (in order to close the keyboard) like this:
UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(closeKeyboard)];
[self.view addGestureRecognizer:gesture];
That gesture recognizer overrides the tap on the UIBarButtonItem, thus I solved by creating a new subview placed immediately below the navigation bar and assigning the gesture recognizer to that view and not to the whole main view.
Mark the method you are targeting at with #objc.

Adding gestures to a draggable view? Swift

I've got buttons on my view that are draggable using touches began/moved/ended.
I want to add a tapped and doubletapped actions for my buttons. Once I switch my button's class to UIButton the action I've created works, but once I change it back to DraggableView the actions stop being called because I guess touchesBegan overrides any other touches on the view.
Is there a good way to do this?
First of all you have to implement UITapGestureRecogizer delegate in your class and add following line of code.
let tap = UITapGestureRecognizer(target: self, action: "handleTap:")
tap.delegate = self
tap.numberOfTapsRequired = 1
yourButton.addGestureRecognizer(tap)
Hope this helps.

How can I add multiple taps to a button or a UIView?

I want one of my screens to be accessed only if the user taps three times on a button within a second. eg. if there's a button on View controller A, a user should tap 3 times within a second on that button to get to View Controller B.
Any help is appreciated!
Buttons are not set up to respond to multiple taps. You'll have to simulate that yourself.
As others have said, you can create a tap gesture recognizer and attach it to any view. For some views you'll need to set the userInteractionEnabled flag to true before it will respond though.
If you want a button to handle double-taps you'll need to have the button with no action installed but a 2 click gesture recognizer attached.
You need to add tap gesture recogniser to your custom View.
-(void)handleTapGesture:(UITapGestureRecognizer *)tapGestureRecognizer{
NSLog(#"3 tapped");
//add code to present another View Controller
}
-(void)buttonView{
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapGesture:)];
tapGestureRecognizer.numberOfTapsRequired=3;
[self.customButtonView addGestureRecognizer:tapGestureRecognizer];
}
Swift:
func handleTapGesture(tapGestureRecognizer: UITapGestureRecognizer) {
NSLog("3 tapped")
//add code to present another View Controller
}
func buttonView() {
var tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "handleTapGesture:")
tapGestureRecognizer.numberOfTapsRequired = 3
self.customButtonView.addGestureRecognizer(tapGestureRecognizer)
}
You can call this method in viewDidAppear.

Recognize swipe gesture in view not in subview

I have added a subview to a View Controller's view. This subview is the view of QLPreviewController.
What I am trying to achieve is to recognize swipe gestures on the subview in the parent view, i.e. the View Controller's view. In the end, I want to be able to swipe left /right on the view to load the next document for preview.
I'm aware of hit testing and understand that by just attaching a gesture recognizer to the parent view, those will not be recognized, since the subview will be the "hit-test" view.
Now what is the best (or easiest) way to recognize those gestures?
Note: I didn't manage to attach the gesture recognizers to the subview, this doesn't seem to work.
* UPDATE *
To make this more clear - this is the code from my ViewController. vContent is just a view in my ViewController, where I add the view of the QLPreviewController:
let pvVc = QLPreviewController()
pvVc.dataSource = self
vContent.addSubview(pvVc.view)
I tried adding the swipe recognizers both to the vContent and the pvVc.view. In both cases no event was fired.
let sgrLeft: UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action:Selector("handleSwipe:"))
sgrLeft.direction = UISwipeGestureRecognizerDirection.Left
sgrLeft.delegate = self
On some other view the code works fine.
Any hint is appreciated!
Thx
Eau
Well, the responder chain, the unknown animal … ;-)
You can subclass the superview and override -hitTest:forEvent:.
You rarely need to call this method yourself, but you might override it to hide touch events from subviews.
Gesture Recognizers Get the First Opportunity to Recognize a Touch, so even the subview is hitTest view. the gestureRecognizer attached on superView can recognizer touch event.

Programmatically created custom view with button target

I'm having an custom UIView subclass which has some UIButtons appended. For every button there is an target action defined on the UIViewController which is including the custom UIView.
Somehow the TouchUpInside event is never being caught within the custom view including ViewController. Since UIViews are part of the UIResponderChain I wonder why events are not being fired? Does it make any sense to delegate the target action or should this be done another way?
Custom UIView Subclass: CustomView
let button = UIButton(frame: CGRectMake(10.0, 10.0, 100.0, 100.0))
button.addTarget(self.delegate, action: "buttonTapped:", forControlEvents: .TouchUpInside)
ViewController
// Include the custom view
let customView = CustomView()
customView.delegate = self
self.view.addSubview(customView)
...
func buttonTapped(sender: AnyObject!) {
// Doesn't get called
}
Do you set userInteractionEnabled to YES on your custom view? It's NO by default on views that are not descended from UIResponder (mostly buttons).
If a view's userInteractionEnabled = NO, it will ignore touch events.
I assume self.delegate is nil when you adding target...
Few solutions:
initialise custom view with delegate (create custom function initWithFrame:delegate)
override setDelegate function for custom view, and add target to button there;
make button variable public, and manually add target to it in your external class
Unfortunately I was missing to declare the frame rect for the buttons - so buttons are being displayed, but they're indeed not clickable.

Resources