I'm trying to detect a double tap with RxSwift
Without RxSwift I would something like this:
private func setupFakePanView() {
let singleTapGesture = UITapGestureRecognizer()
let doubleTapGesture = UITapGestureRecognizer()
singleTapGesture.numberOfTapsRequired = 1
doubleTapGesture.numberOfTapsRequired = 2
singleTapGesture.addTarget(self, action: #selector(self.tapped))
doubleTapGesture.addTarget(self, action: #selector(self.doubleTapped))
someView.addGestureRecognizer(singleTapGesture)
someView.addGestureRecognizer(doubleTapGesture)
singleTapGesture.require(toFail: doubleTapGesture)
}
@objc private func tapped() {
// Do something
}
@objc private func doubleTapped() {
// Do something else
}
Is there a way I could achieve the same with RxSwift, RxCocoa and RxGesture? I've tried the following but of course it doesn't work:
someView.rx
.tapGesture(numberOfTouchesRequired: 1, numberOfTapsRequired: 1)
.when(.recognized)
.subscribe(onNext: { _ in
// Do something
})
.disposed(by: bag)
someView.rx
.tapGesture(numberOfTouchesRequired: 1, numberOfTapsRequired: 2)
.when(.recognized)
.subscribe(onNext: { _ in
// Do something else
})
.disposed(by: bag)
Is there way to let the first tapGesture know the second has to fail?
I've found 2 solutions to solve this problem!
UITapGestureRecognizer
let doubleTapGesture = UITapGestureRecognizer()
doubleTapGesture.numberOfTapsRequired = 2
let singleTapGesture = UITapGestureRecognizer()
singleTapGesture.numberOfTapsRequired = 1
singleTapGesture.require(toFail: doubleTapGesture)
let singleTap = someView.rx
.gesture(singleTapGesture)
.when(.recognized)
.subscribe(onNext: { _ in
// Do something
})
.disposed(by: bag)
let doubleTap = someView.rx
.gesture(doubleTapGesture)
.when(.recognized)
.subscribe(onNext: { _ in
// Do something else
})
.disposed(by: bag)
or..
UIGestureRecognizerDelegate
Thanks Kishan for suggesting Jegnux's answer!
1 - Set a custom delegate for the single tap gesture...
someView.rx
.tapGesture(
numberOfTouchesRequired: 1,
numberOfTapsRequired: 1,
configuration: { [weak self] gesture, delegate in
gesture.delegate = self
}
)
.subscribe(onNext: { _ in
// Do something
})
.disposed(by: bag)
// double tap same as before
2 - Implement gestureRecognizer(_:shouldRequireFailureOf:)
extension MyController: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if let gesture = otherGestureRecognizer as? UITapGestureRecognizer, gesture.numberOfTapsRequired == 2 {
return true
}
return false
}
}
Both solutions work fine.