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.
-
How did you added `BarButtonItem` to your `NavigationBar`? – emrcftci Mar 09 '20 at 07:42
-
Did you read this old thread ? https://stackoverflow.com/questions/2655630/how-can-you-add-a-uigesturerecognizer-to-a-uibarbuttonitem-as-in-the-common-undo. problem is that barButton are not UIButtons, so you need some workaround. – claude31 Mar 09 '20 at 08:10
-
you can create custom navBar instead of default one, and handle tap actions by using tapGestures. – Mudassir Asghar Mar 09 '20 at 13:13
5 Answers
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

- 3,355
- 3
- 21
- 35

- 94
- 10
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")
}

- 3,355
- 3
- 21
- 35
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.

- 2,790
- 6
- 29
- 33
-
1This is the Solution. Works also if setting it in viewWillAppear. Thank you. – kaharoth Sep 21 '22 at 10:17
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

- 9,364
- 2
- 17
- 30
-
This is triggered only on button release. It is good to ignore the long press though. – kaharoth Sep 21 '22 at 09:58
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 :)

- 1,520
- 11
- 27
-
Unfortunately doing so you can't use system buttons like the share action button. Look at the solution posted by The Tom. That's what is working for me. – kaharoth Sep 21 '22 at 10:20