Touch down repeat event does not works - ios

I want my button to change its background image when the user clicks on it twice. For this purpose i am using touchDownRepeat event. However it does not works.
button.addTarget(self, action: #selector(clickedRepeatOnPlate), for: .touchDownRepeat)

As for the Apple's oficial documentation about .touchDownRepeat :
A repeated touch-down event in the control; for this event the value of the UITouch tapCount method is greater than one.
This event will trigger every time the user taps the button more than once, so four taps will trigger the event three times.
To trigger only double taps, you need to create a UITapGesture and set 2 on its numberOfTapsRequired:
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(clickedRepeatOnPlate))
tapGesture.numberOfTapsRequired = 2
button.addGestureRecognizer(tapGesture)
Edit
If you need to get the sender button as a function parameter, you can do as follows:
func addDoubleTapEvent() {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(clickedRepeatOnPlate(gesture:)))
tapGesture.numberOfTapsRequired = 2
button.addGestureRecognizer(tapGesture)
}
#objc func clickedRepeatOnPlate(gesture: UITapGestureRecognizer) {
guard let button = gesture.view as? UIButton else { return }
print(button.titleLabel?.text)
}
Output
Optional("button")

This let you to set a gesture for double tap on a view.
let tap = UITapGestureRecognizer(target: self, action: #selector(doubleTapped))
tap.numberOfTapsRequired = 2
view.addGestureRecognizer(tap)
Remember that a UIButton is a UIView

Related

UITapGestureRecognizer doubletap still triggers singletap action

I have an UIView with both single and double tap recognizers but with different actions of course. The single tap recognizer works well but the double tap recognizer still calls and triggers the single tap...
Below is my implementation:-
let singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(toggleIsVisible))
singleTapGesture.numberOfTapsRequired = 1
self.addGestureRecognizer(singleTapGesture)
let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(test))
doubleTapGesture.numberOfTapsRequired = 2
self.addGestureRecognizer(doubleTapGesture)
singleTapGesture.require(toFail: doubleTapGesture)
singleTapGesture.delaysTouchesBegan = true
doubleTapGesture.delaysTouchesBegan = true
Note: "self" is a UIView class
You can achieve it like this as well ... add delay to your single tap to check if its double tap.. if double tap then cancel performance of single tap .. simple methodology
var tapCount = 0
func tapGestureRecognizer() {
tapCount += 1
switch (tapCount)
{
case 1: //single tap
self.perform(#selector(singleTap), with: nil, afterDelay: 0.2)
case 2: //double tap
NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(singleTap), object: nil)
doubleTap()
break;
default:
break;
}
if (tapCount>2){
tapCount = 0
}
}
#objc func singleTap(){
}
#objc func doubleTap() {
}
Your code should work fine without triggering the singleTap gesture for doubleTap events. So why is the singleTap event gesture triggering for doubleTap event? Are you sure these are the only gestures you're adding? Make sure you're not adding any other customisation that might alter the gesture events. You don't need these lines:
singleTapGesture.delaysTouchesBegan = true
doubleTapGesture.delaysTouchesBegan = true

figure out which button was pressed while differ between long-press and tap. swift

So I have listeners for a long and short-press on buttons, but I need to know what button was pressed.
Is it possible to find out what button was pressed in the tap and long function, or will I need to do two functions for each button?
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tap))
let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(long))
longGesture.minimumPressDuration = 0.5
smallOption.addGestureRecognizer(tapGesture)
mediumOption.addGestureRecognizer(tapGesture)
largeOption.addGestureRecognizer(tapGesture)
smallOption.addGestureRecognizer(longGesture)
mediumOption.addGestureRecognizer(longGesture)
largeOption.addGestureRecognizer(longGesture)
#objc func tap(_ sender: UIGestureRecognizer){
print("short-press")
}
#objc func long(_ sender: UIGestureRecognizer){
print("long-press")
}
The main issue, in this case, is both gestures will be added ONLY for the largeOption button! To clarify, the gesture is added only for one component, which in your case, it should be added only for the latest one (which is largeOption):
smallOption.addGestureRecognizer(tapGesture) <-- skipped
mediumOption.addGestureRecognizer(tapGesture) <-- skipped
largeOption.addGestureRecognizer(tapGesture) <-- added
smallOption.addGestureRecognizer(longGesture) <-- skipped
mediumOption.addGestureRecognizer(longGesture) <-- skipped
largeOption.addGestureRecognizer(longGesture) <-- added
Logically speaking, this might be the answer to your question:
Is it possible to find out what button was pressed in the tap and long function, or will I need to do two functions for each button?
you need to add two gestures for each button because a particular gesture can only be added to one view.
However, you don't have to declare new action methods in addition to #objc func tap(_ sender: UIGestureRecognizer) and #objc func long(_ sender: UIGestureRecognizer) existing ones. What you could do instead is to check the sender's view. Example:
Let's assume that we manually added tow gestures for each button:
// gestures:
let smallOptionTapGesture = UITapGestureRecognizer(target: self, action: #selector(tap))
let smallOptionLongGesture = UILongPressGestureRecognizer(target: self, action: #selector(long))
smallOptionLongGesture.minimumPressDuration = 0.5
let mediumOptionTapGesture = UITapGestureRecognizer(target: self, action: #selector(tap))
let mediumOptionLongGesture = UILongPressGestureRecognizer(target: self, action: #selector(long))
mediumOptionLongGesture.minimumPressDuration = 0.5
let largeOptionTapGesture = UITapGestureRecognizer(target: self, action: #selector(tap))
let largeOptionLongGesture = UILongPressGestureRecognizer(target: self, action: #selector(long))
largeOptionLongGesture.minimumPressDuration = 0.5
// adding them:
smallOption.addGestureRecognizer(smallOptionTapGesture)
mediumOption.addGestureRecognizer(mediumOptionTapGesture)
largeOption.addGestureRecognizer(largeOptionTapGesture)
smallOption.addGestureRecognizer(smallOptionLongGesture)
mediumOption.addGestureRecognizer(mediumOptionLongGesture)
largeOption.addGestureRecognizer(largeOptionLongGesture)
Therefore, what you could do is:
#objc func tap(_ sender: UIGestureRecognizer) {
// an example of how you could check the button
if sender.view == smallOption {
print("small short-press")
} else if sender.view == mediumOption {
print("medium short-press")
} else if sender.view == largeOption {
print("large short-press")
}
}
#objc func long(_ sender: UIGestureRecognizer) {
// you could apply the same above approach here
}
The other option is to create action methods for each button separately.
You do not need two functions for the same gesture for each button. Change the method definition to accept UIButton (in your case) instead of UIGestureRecognizer. Afterwards, check the sender by verifying the tag or the type directly...
#objc func tap(_ sender: UIButton){
switch sender {
case button1: // or by tags of buttons
case button2:
...
default: break
}

How to detect longpress in BarButtonitem

I have a UIBarButtonItem in navigation bar. When a user clicks it, it pops to another viewController.
Now i want that when user long-press on that button (navigation bar button) I want to show a help message.
I want help to detect the onlick event and longpress event separately.
You should create a button and set UITapGestureRecognizer & UILongPressGestureRecognizer to your button
// Create a button
let yourButton = UIButton()
yourButton.backgroundColor = .red
yourButton.setTitle("long press", for: .normal)
// Create a tap gesture recognizer
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTap))
// Create a long gesture recognizer
let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(long))
// You can set minimum duration of the press action
longGesture.minimumPressDuration = 3 //The default duration is 0.5 seconds.
// Add your gestures to button
yourButton.addGestureRecognizer(longGesture)
yourButton.addGestureRecognizer(tapGesture)
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: yourButton)
#objc private func didTap() {
print("Did Tap")
}
#objc private func long() {
// You can show the help message in here
print("Long press")
}
try this in view didload:
let back = UIImage(named: "header_backarrow")
let backView = UIImageView(image: back)
backView.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissManual))
backView.addGestureRecognizer(tap)
let backItem = UIBarButtonItem(customView: backView)
navigationItem.leftBarButtonItem = backItem
In the viewDidAppear of your view controller you can add this :
let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(myCalledFunction))
(myUIBarButton.value(forKey: "view") as? UIView)?.addGestureRecognizer(gestureRecognizer)
This is difficult because UIBarButton doesn't really expose its view and so you cannot directly add a gestureRecognizer to it.
You can however get a reference to its view by using the value(forKey:) method and then play with it.
Do not do this in the viewDidLoad as it is necessary for the view to have already been created in order for this to work.
All of the other answers require implementing a UIBarButtonItem(customView:) to achieve this. However this can be implemented with any UIBarButtonItem instance without implementing your own gesture recognizer code.
An #IBAction can actually be passed a second parameter containing the UIEvent triggering the action. For example, instead of defining -
#objc func doSomething(sender: UIBarButtonItem) {
}
We can define -
#objc func doSomething(sender: UIBarButtonItem, forEvent event: UIEvent) {
guard let touch = event.allTouches?.first else { return }
if touch.tapCount == 1 {
// Handle tap
} else if touch.tapCount == 0 {
// Handle long press
}
}
Source : http://li366-68.members.linode.com/2016/09/07/detecting-long-presses-on-uibarbuttonitems.html
so I found that UIBarButton has not property like longpress so all I do is take a UIButton give it longpress gesture and add that UIButton in navigation bar as UIBarButtonItem.
I hope it will helpful for someone else who is facing same problem.
let btn = UIButton(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
btn.backgroundColor = .green
let gesture = UILongPressGestureRecognizer(target: self, action: #selector(longpress))
btn.addGestureRecognizer(gesture)
let barbtn = UIBarButtonItem(customView: btn)
self.navigationItem.rightBarButtonItem = barbtn
thank you :)

Calling Long Press Button action only once not rapid fire

Here is my code for a long press. When I long-press the button, it keeps getting called. How do I set it up so it only gets called once and then gets called again only once the finger is release and the long press is started again?
let tapGesture = UITapGestureRecognizer(target: self, action: #selector (tap))
let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(long))
tapGesture.numberOfTapsRequired = 1
self.reminderButton.addGestureRecognizer(tapGesture)
self.reminderButton.addGestureRecognizer(longGesture)
use this code in your selector
#objc func gestureAction(gesture: UIGestureRecognizer) {
if let longPress = gesture as? UILongPressGestureRecognizer {
if longPress.state == UIGestureRecognizer.State.began {
} else {
}
}

Single tap, created by UITapGestureRecognizer, doesn't work on UIButton

I have a lot of UIButtons without any acion. I want call some action in tap handler function. I create single tap with UITapGestureRecognizer. When I tap not on my UIButton, single tap handler work. When I tap on my UIButton, I see animation of pressing this button, but single tap handler doesn't work. Also I create double tap, and it works fine.
Question №1
What I can do with single tap? Handler should work, when I tap on my UIButton.
Question №2
How I can get UIButton in tap handler? I need get text label from this button.
Part of my code:
override func viewDidLoad() {
...
let singleTap = UITapGestureRecognizer(target: self, action: "singleTap:")
singleTap.numberOfTapsRequired = 1
singleTap.numberOfTouchesRequired = 1
view.addGestureRecognizer(singleTap)
let doubleTap = UITapGestureRecognizer(target: self, action: "doubleTap:")
doubleTap.numberOfTapsRequired = 2
doubleTap.numberOfTouchesRequired = 1
view.addGestureRecognizer(doubleTap)
singleTap.requireGestureRecognizerToFail(doubleTap)
...
}
func doubleTap(sender: UIGestureRecognizer) {
if sender.state == .Ended {
print("doubleTap")
}
}
func singleTap(sender: UIGestureRecognizer) {
if sender.state == .Ended {
print("singleTap")
}
}
func addButton(time:String, x:CGFloat, y:CGFloat, width:CGFloat, height:CGFloat, tag: Int) -> UIButton {
let button = UIButton(type: UIButtonType.System) as UIButton
button.frame = CGRectMake(x, y, width, height)
button.setTitle(time, forState: UIControlState.Normal)
button.tag = tag
self.scrollView.addSubview(button)
return button
}
If you want to add TapGesture into Button then do it like this way:
let singleTap = UITapGestureRecognizer(target: self, action: "singleTap:")
singleTap.numberOfTapsRequired = 1
singleTap.numberOfTouchesRequired = 1
yourButton.addGestureRecognizer(singleTap)

Resources