UITapGestureRecognizer called immediately
You should use following syntax:
let gest = UITapGestureRecognizer(target: self, action: #selector(imgPressed))
Note, that Selector
can accept initial type Void
as well as String
. Properly old-style Selector
initialization looks like this:
let action: Selector = Selector("imgPressed")
Now you may check, that if you will try combine new style with old style you will get compilation error:
let action = Selector(imgPressed) // Error!
Funny thing is that you probably will try to resolve this error by appending bracers, and you will not have any errors after that! But this is completely useless. Look at following 3 lines of code, they are equivalent
let action = Selector(imgPressed())
let action = Selector(Void())
let action = Selector()
exept one thing - in first line you called imgPressed()
function, returned Void
, by your hands. Thats it =)
UITapGestureRecognizer called only once
My code was fine answering my own issue.
The problem was the line: addSubview(imageView)
I was adding 4 placeholder (about 300px) to a container smaller than the sum of the widths of all my placeholders.
Although I was seeing all the placeholders correctly displayed, the frame wasn't big enough to contain them and so the double tap not recognised.
Making the container bigger solved the issue.
Swift3 iOS - How to make UITapGestureRecognizer trigger function
From your code you are using swift 3.0 so change your selector
syntax like this
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tapBlurButton(_:)))
and Your function like this
func tapBlurButton(_ sender: UITapGestureRecognizer) {
print("Please Help!")
}
Edit:
Not idea that you are using button with tap gesture, instead of that use inbuilt method addTarget
for button no need to create tap gesture for it like this
qsBlurButton.addTarget(self, action: #selector(self.tapBlurButton(_:)), forControlEvents: .TouchUpInside)
func tapBlurButton(_ sender: UIButton) {
print("Please Help!")
}
Swift UITapGestureRecognizer not calling
The target should be the coordinator
(which is a persistent entity, unlike the transient View), not self
.
let focusGesture = UITapGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.tapFocus(_:)))
Gesture recognizer code being called twice after leaving and coming back to view
Move the tap gesture code into viewDidLoad
and not viewDidAppear
let doubleTap = UITapGestureRecognizer(target: self, action: #selector(self.doubleTapAction(sender:)))
doubleTap.numberOfTapsRequired = 2
self.addGestureRecognizer(doubleTap)
viewDidAppear
will be called every time you go back to that screen. You don't need to remove the gesture recognisers when you move to a different screen - they will only be called when that view is visible.
Why is touchesCancelled being called after UITapGestureRecognizer?
That's just what a gesture recognizer is / does. When a gesture recognizer recognizes its gesture, the touches for this gesture recognizer are sent to their hit-test views as a touchesCancelled(_:with:)
message, and then no longer arrive at those views. The gesture recognizer takes over so it signs the view off from its touch sequence in good order.
If you're going to have both a gesture recognizer and manual touch events, you have to do more work to mediate between them. If you really don't want the standard behavior, you can set the gesture recognizer's cancelsTouchesInView
property to false
.
How to create UIBarButton to call UITapGestureRecognizer function using Swift?
If you need to call both these tap gesture recognizer functions from a UIBarButtonItem
, your best bet is to create a custom view bar button item and add gesture recognizers to that custom view. Something like this would work:
let tapGestureView = UIView() // initialize & size this as you need
tapGestureView.addGestureRecognizer(UITapGestureRecognizer(action: #selector(handleCardTap(_:)), target: self))
tapGestureView.addGestureRecognizer(UITapGestureRecognizer(action: #selector(handleCardPan(_:)), target: self))
let barButton = UIBarButtonItem(customView: tapGestureView)
Here are some additional resources for UITapGestureRecognizers
and UIBarButtonItems. It seems a bit odd to set up 2 different tap gestures for the same view, though, and one of them being a pan action (at least by name) seems odd, but this is how you'd accomplish that!
Triggering UITapGestureRecognizers from overlapping Views
First you should conform to UIGestureRecognizerDelegate
in your VC, and then implement the delegate func of shouldRecognizeSimultaneouslyWith
. Inside the function, you should detect if the gestureRecognizer
, and the otherGestureRecognizer
are the wants you want, and if so, you should allow them to work simultaneously,
Conform to delegate, and Declare gesture recognizers outside of
viewDidLoad
(because you need to access them in the delegate method later.)var mainGestureRecognizer = UITapGestureRecognizer()
var subGestureRecognizer = UITapGestureRecognizer()Initialize your recognizers, and set your VC as their delegate:
mainGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(mainGestureActivated))
subGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(subViewGestureActivated))
mainGestureRecognizer.delegate = self
subGestureRecognizer.delegate = selfImplement the delegate function mentioned above to allow simultaneous recognition for subView and mainView:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer == subGestureRecognizer && otherGestureRecognizer == mainGestureRecognizer {
return true
}
return false
}
And if you want it to work for 4 different subviews, then you should check with else if statements inside the delegate method.
Resolve UITapGestureRecognizer and UILongPressGestureRecognizer simultaneously and fire UIGestureRecognizer.State.began on finger touch down
I wonder if your implementation of shouldRequireFailureOf
is causing an issue?
This works just fine for me (note: I used .minimumPressDuration = 0.25
because it's a little difficult to tap in under 0.1 seconds):
class GestureTestViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupTapGestures()
}
private func setupTapGestures() -> Void {
let singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(_:)))
view.addGestureRecognizer(singleTapGesture)
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPressGesture(_:)))
longPressGesture.minimumPressDuration = 0.25
view.addGestureRecognizer(longPressGesture)
}
@objc func handleLongPressGesture(_ gesture: UILongPressGestureRecognizer) -> Void {
if gesture.state == .began {
print("Did Long Press (began)")
}
if gesture.state == .ended {
print("Did Long Press (ended)")
}
}
@objc func handleTapGesture(_ gesture: UITapGestureRecognizer) -> Void {
print("Did Single Tap")
}
}
When I tap, I get "Did Single Tap" in the debug console.
When I tap and hold, I quickly get "Did Long Press (began)", and on finger-lift I get "Did Long Press (ended)"
Related Topics
Swiftui Card Flip Animation with Two Views, One of Which Is Embedded Within a Stack
Swift: Triggering Tableviewcell to Lead to a Link in a Uiwebview in Another Viewcontroller
Delegates: Pass Data Without Segue
Audio Information of Current Track iOS Swift
The Array Value Should Be Sort Like (Alphabetic, Numbers and Special Characters)
How Should Secure Transport Tls Be Used with Bsd Sockets in Swift
Why Tabbar Hides After the Segue
Ios: How to Create Expandable Tableview in Swift Without Using Third Party Libraries or Pods
Table View Controller Duplicate Itself in iOS Swift
iOS Pass Data Back from Viewcontroller2 to Viewcontroller 1 with Presentmodalsegue
How to Change a View from Portrait Mode to Landscape Mode and Lock It
Live Render Iboutlet Connected Subviews via Ibinspectable Properties
How to Get the Index (String.Index) Value from the Cursor Position of a Uitextview Element in Swift
How to Debug Swift Playgroundbook