How to accelerate the identification of a single tap over a double tap?
Full Implementation of Markus's Swift 3 version of eladleb's original solution.
Create subclass file UIShortTapGestureRecogninzer
import UIKit
import UIKit.UIGestureRecognizerSubclass
class UIShortTapGestureRecognizer: UITapGestureRecognizer {
let tapMaxDelay: Double = 0.3 //anything below 0.3 may cause doubleTap to be inaccessible by many users
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event)
DispatchQueue.main.asyncAfter(deadline: .now() + tapMaxDelay) { [weak self] in
if self?.state != UIGestureRecognizerState.recognized {
self?.state = UIGestureRecognizerState.failed
}
}
}
}
Note: When adding UIGestureRecognizer
only doubleTap needs to be of type UIShortTapGestureRecognizer
& singleTap.require(toFail: doubleTap)
is required.
func addBoth (views: UIView, selectorSingle: Selector, selectorDouble: Selector) {
let doubleTap:UIShortTapGestureRecognizer = UIShortTapGestureRecognizer(target: self, action: selectorDouble)
doubleTap.numberOfTapsRequired = 2
views.addGestureRecognizer(doubleTap)
let singleTap:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: selectorSingle)
singleTap.numberOfTapsRequired = 1
singleTap.require(toFail: doubleTap)
views.addGestureRecognizer(singleTap)
}
I found the answer on this link
The swift version:
class UIShortTapGestureRecognizer: UITapGestureRecognizer {
let tapMaxDelay: Double = 0.3
override func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) {
super.touchesBegan(touches, withEvent: event)
delay(tapMaxDelay) {
// Enough time has passed and the gesture was not recognized -> It has failed.
if self.state != UIGestureRecognizerState.Ended {
self.state = UIGestureRecognizerState.Failed
}
}
}
}
With delay(delay: Double, closure:()->())
:
class func delay(delay:Double, closure:()->()) {
dispatch_after(dispatch_time( DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), closure)
}