How to detect finger location in function - ios

I want to use double click. I have written function doubleTap. How to recognize location of finger?
override func viewDidLoad()
{
super.viewDidLoad()
let doubleTap = UITapGestureRecognizer(target: self, action: "doubleTap")
doubleTap.numberOfTapsRequired = 2
doubleTap.numberOfTouchesRequired = 1
view.addGestureRecognizer(doubleTap)
}
func doubleTap()
{
}

You can use location(ofTouch:in:) to get the location of the touch. However, you need access to the gesture recognizer from inside the function where you want to access the location, so you should declare doubleTap as an instance property of your class.
class YourViewController: UIViewController {
let doubleTap = UITapGestureRecognizer(target: self, action: #selector(YourViewController.doubleTap))
override func viewDidLoad(){
super.viewDidLoad()
doubleTap.numberOfTapsRequired = 2
doubleTap.numberOfTouchesRequired = 1
view.addGestureRecognizer(doubleTap)
}
func doubleTap(){
let touchLocation = doubleTap.location(ofTouch: numberOfTouches-1,in: nil)
}
}
Change the input parameters to the function if you want to change whether you need to get the first or last touch's location or if you want to get the location relative to a subview.

You can get the gesture recognizer as a parameter
override func viewDidLoad()
{
super.viewDidLoad()
let doubleTap = UITapGestureRecognizer(target: self, action: #selector(doubleTapFunc))
doubleTap.numberOfTapsRequired = 2
doubleTap.numberOfTouchesRequired = 1
view.addGestureRecognizer(doubleTap)
}
func doubleTapFunc(_ sender: UITapGestureRecognizer)
{
// Use 'sender' here to get the location
if sender.state == .ended {
// handling code
let location = sender.location(ofTouch: 0, in: self.view!)
}
}

Related

Is there any property need to set-up to allow the double-tap (Swift)

I can not detect the double-tap in screen? Do i need to turn on the property in the project?
So i try this, but it doesn't work:
let tapRec = UITapGestureRecognizer()
tapRec.addTarget(self, action: #selector(GameScene.doubleTap))
tapRec.numberOfTapsRequired = 2
self.view!.addGestureRecognizer(tapRec)
#objc func doubleTap(){
print ("tap")
}
Try this:
let tapRec = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap(_:)))
tapRec.delegate = self
tapRec.numberOfTapsRequired = 2
view.userInteractionEnabled = true
view.addGestureRecognizer(tapRec)
And then your function:
extension YourViewController: UIGestureRecognizerDelegate {
func handleDoubleTap(_ gesture: UITapGestureRecognizer){
print("doubletapped")
}
}
Hope this helps!

Fast tap gestures in Swift 4 and iOS 11

I just made a simple app to try out any type of gestures. I got to the tap gesture. So I thought, what if I made a fast tap game kind of application that counts the amount of taps the user performed. But soon enough I ran into some issues.
It did not count all the taps. If I began to tap as fast as possible, but it skipped taps.
The idea is I programmatically created a view in the superview and added a tapGestureRecognizer on the view. And simply put the “taps” into a label in the app.
It seems to fail to receive a system gesture on time.
The code:
let tap = UITapGestureRecognizer(target: self, action: #selector(tapped(sender:)));
tap.numberOfTapsRequired = 1;
animationView.isUserInteractionEnabled = true;
animationView.addGestureRecognizer(tap);
The function:
#objc func tapped (sender :UITapGestureRecognizer) {
self.counter += 1;
self.lblScore.text = String(self.counter);
}
I have an animationView that I made "tappable" and it works. Every time I tap the animationView it increments the value of 'counter' that works! but every time I get this error if I tap too fast:
<_UISystemGestureGateGestureRecognizer: 0x1c01c4b00>: Gesture: Failed to receive system gesture state notification before next touch
Create Gesture :
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
panGesture.delegate = self
Button.addGestureRecognizer(panGesture)
let longTapGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongTapGesture(_:)))
Button.addGestureRecognizer(longTapGesture)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(_:)))
Button.addGestureRecognizer(tapGesture)
let rotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(handleRotateGesture(_:)))
rotateGesture.delegate = self
Button.addGestureRecognizer(rotateGesture)
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinchGesture(_:)))
pinchGesture.delegate = self
Button.addGestureRecognizer(pinchGesture)
Gesture click Event :
extension AddTextVC: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
#IBAction func handlePanGesture(_ recognizer: UIPanGestureRecognizer) {
}
#IBAction func handlePinchGesture(_ recognizer: UIPinchGestureRecognizer) {
}
#IBAction func handleRotateGesture(_ recognizer: UIRotationGestureRecognizer)
{
}
#IBAction func handleTapGesture(_ recognizer: UITapGestureRecognizer) {
}
#IBAction func handleLongTapGesture(_ recognizer: UITapGestureRecognizer) {
}
}

How can we add a UIGestureRecognizer to Outlet Collection?

I'm trying to add a tap gesture to an outlet collection of labels [UILabel], like this:
#IBOutlet var subLabels: [UILabel]!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(HomePageViewController.selectSubLabel(tap:)))
tap.numberOfTapsRequired = 1
tap.cancelsTouchesInView = false
for i in (0..<(subLabels.count)) {
subLabels[i].addGestureRecognizer(tap)
}
}
func selectSubLabel(tap: UITapGestureRecognizer) {
print("Gesture Is WORKING!")
}
and i tried to add it on a single label in storyboard; but NONE are working.
Firstly, you need to allow user interaction on a label (it is turned off by default):
for i in (0..<(subLabels.count)) {
subLabels[i].isUserInteractionEnabled = true
subLabels[i].addGestureRecognizer(tap)
}
but gesture recognizer can observe for gestures only in one view.
So, there are two options:
I. Dedicated gesture recognizer for every label
for i in (0..<(labels.count)) {
let tap = UITapGestureRecognizer(target: self, action: #selector(selectSubLabel(tap:)))
labels[i].isUserInteractionEnabled = true
labels[i].addGestureRecognizer(tap)
}
II. One gesture recognizer for the parent view of the labels
override func viewDidLoad() {
super.viewDidLoad()
for i in (0..<(labels.count)) {
subLabels[i].isUserInteractionEnabled = true
}
let tap = UITapGestureRecognizer(target: self, action: #selector(selectSubLabel(tap:)))
view.addGestureRecognizer(tap)
}
func selectSubLabel(tap: UITapGestureRecognizer) {
let touchPoint = tap.location(in: view)
guard let label = subLabels.first(where: { $0.frame.contains(touchPoint) }) else { return }
// Do your stuff with the label
}
Please check the User Interaction Enabled Attribute of your UIlabel's in Attribute inspector of Xcode. User Interaction Enabled must be ticked for detecting the tap. Please see the picture below,

Add parameter on UITapGestureRecognizer

I would like to ask on how to add a parameter on the UITapGestureRecognizer on my UILabel. So far this is what I got:
self.feedSource.text = source_link
self.feedSource.userInteractionEnabled = true
let feedSourceTapGesture = UITapGestureRecognizer(target: self, action: Selector("openLinkFromFeedSource"))
self.feedSource.addGestureRecognizer(feedSourceTapGesture)
func openLinkFromFeedSource() {
print("tapped")
}
What I want to achieve is when I tapped the label, from openLinkFromFeedSource I can get the value of the self.feedSource.text
Thanks!
You should get this from tap gesture action like this:
func didTapOnView(tap: UITapGestureRecognizer) {
let label = tap.view
// do with that label
}
try this
self.feedSource.userInteractionEnabled = true
let feedSourceTapGesture = UITapGestureRecognizer(target: self, action: Selector("openLinkFromFeedSource:"))
self.feedSource.addGestureRecognizer(feedSourceTapGesture)
func openLinkFromFeedSource(sender: UITapGestureRecognizer) {
let label = sender.view
print("tapped")
}

Swift: Long Press Gesture Recognizer - Detect taps and Long Press

I want to wire an action such that if the gesture is a tap, it does animates an object in a particular way but if the press duration was more than .5 secs it does something else.
Right now, I just have the animation hooked up. I don't know how I can differentiate between a long press and a tap?
How do I access the press duration to achieve the above?
#IBAction func tapOrHold(sender: AnyObject) {
UIView.animateKeyframesWithDuration(duration, delay: delay, options: options, animations: {
UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0, animations: {
self.polyRotate.transform = CGAffineTransformMakeRotation(1/3 * CGFloat(M_PI * 2))
})
UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0, animations: {
self.polyRotate.transform = CGAffineTransformMakeRotation(2/3 * CGFloat(M_PI * 2))
})
UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0, animations: {
self.polyRotate.transform = CGAffineTransformMakeRotation(3/3 * CGFloat(M_PI * 2))
})
}, completion: { (Bool) in
let vc : AnyObject! = self.storyboard?.instantiateViewControllerWithIdentifier("NextView")
self.showViewController(vc as UIViewController, sender: vc)
})
Define two IBActions and set one Gesture Recognizer to each of them. This way you can perform two different actions for each gesture.
You can set each Gesture Recognizer to different IBActions in the interface builder.
#IBAction func tapped(sender: UITapGestureRecognizer)
{
println("tapped")
//Your animation code.
}
#IBAction func longPressed(sender: UILongPressGestureRecognizer)
{
println("longpressed")
//Different code
}
Through code without interface builder
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "tapped:")
self.view.addGestureRecognizer(tapGestureRecognizer)
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: "longPressed:")
self.view.addGestureRecognizer(longPressRecognizer)
func tapped(sender: UITapGestureRecognizer)
{
println("tapped")
}
func longPressed(sender: UILongPressGestureRecognizer)
{
println("longpressed")
}
Swift 5
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapped))
self.view.addGestureRecognizer(tapGestureRecognizer)
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(longPressed))
self.view.addGestureRecognizer(longPressRecognizer)
#objc func tapped(sender: UITapGestureRecognizer){
print("tapped")
}
#objc func longPressed(sender: UILongPressGestureRecognizer) {
print("longpressed")
}
For swift2
let lpgr = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
lpgr.minimumPressDuration = 0.5
lpgr.delaysTouchesBegan = true
lpgr.delegate = self
self.featuredCouponColView.addGestureRecognizer(lpgr)
Action
//MARK: - UILongPressGestureRecognizer Action -
func handleLongPress(gestureReconizer: UILongPressGestureRecognizer) {
if gestureReconizer.state != UIGestureRecognizerState.Ended {
//When lognpress is start or running
}
else {
//When lognpress is finish
}
}
For Swift 4.2/ Swift 5
let lpgr = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
lpgr.minimumPressDuration = 0.5
lpgr.delaysTouchesBegan = true
lpgr.delegate = self
self.colVw.addGestureRecognizer(lpgr)
//MARK: - UILongPressGestureRecognizer Action -
#objc func handleLongPress(gestureReconizer: UILongPressGestureRecognizer) {
if gestureReconizer.state != UIGestureRecognizer.State.ended {
//When lognpress is start or running
}
else {
//When lognpress is finish
}
}
Through code without interface builder
// Global variables declaration
var longPressed = false
var selectedRow = 0
override func viewDidLoad() {
super.viewDidLoad()
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(ContactListTableViewController.handleLongPress(_:)))
longPressGesture.minimumPressDuration = 1.0 // 1 second press
longPressGesture.allowableMovement = 15 // 15 points
longPressGesture.delegate = self
self.tableView.addGestureRecognizer(longPressGesture)
}
// Long tap work goes here !!
if (longPressed == true) {
if(tableView.cellForRowAtIndexPath(indexPath)?.accessoryType == .Checkmark){
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .None
self.selectedRow -= 1
if(self.selectedRow == 0){
self.longPressed = false
}
} else {
self.selectedRow += 1
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark
}
} else if(self.selectedRow == 0) {
// Single tape work goes here !!
}
But the only problem is the long press gesture runs two times. If you have found any solution do comment below !
Swift 5 using interface builder
for the normal tap you can simply create a touch up inside action from your button.
for the long press, create an outlet for your button, create the tap gesture recognizer and set it to the button then create the selector method to perform the long press tasks.
#IBOutlet var myButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(addToListButtonLongPress(_:)))
longPressRecognizer.numberOfTouchesRequired = 1
longPressRecognizer.allowableMovement = 10
longPressRecognizer.minimumPressDuration = 0.5
myButton.addGestureRecognizer(longPressRecognizer)
}
// Connected to myButton in interface builder.
#IBAction func myButtonTapped(_ sender: UIButton) {
print("button tapped")
}
#objc func myButtonLongPressed(_ sender: UILongPressGestureRecognizer) {
print("button long pressed")
}

Resources