UIBarButtonItem selector not working
try with inside scope once
override func viewDidLoad() {
super.viewDidLoad()
let rightButton = UIBarButtonItem(title: "Right", style: .plain, target: self, action: #selector(self.onRightLeftClick(_ :)))
rightButton.tag = 1
let leftButton = UIBarButtonItem(title: "Left", style: .plain, target: self, action: #selector(self.onRightLeftClick(_ :)))
rightButton.tag = 2
self.navigationItem.rightBarButtonItem = rightButton
self.navigationItem.leftBarButtonItem = leftButton
}
handle the action as
func onRightLeftClick(_ sender: UIBarButtonItem){
if sender.tag == 1{
// rightButton action
}else{
// leftButton action
}
}
#selector function of UIBarButtonItem not firing when pressed
Maybe the rest of the instance haven't initialised at the time your code is executed. Have you tried doing this in viewDidLoad
? If not, try doing that:
override func viewDidLoad() {
super.viewDidLoad()
configureYourBarButtonHere()
}
I remember seeing a lot of questions that highlight this issue, with this solution. Here are a couple ones I could find for now:
UIBarButtonItem selector not working
https://stackoverflow.com/a/49283627/9293498
#selector on UIBarButtonItem
No quotes.
#selector(Utils.menuClicked(_:))
func menuClicked
should be in your view controller class. But if for some reason it isn't, you can do
class Utils {
static let instance = Utils()
let menuButton = UIBarButtonItem(image: UIImage(named: "menu"),
style: UIBarButtonItemStyle.Plain ,
target: Utils.instance, action: #selector(Utils.menuClicked(_:)))
@objc func menuClicked(sender: UIBarButtonItem) {
// do stuff
}
}
UIBarButtonItem not firing up selector action
The code you provided should be working so you need to provide more context (show more of your view controller class where this is implemented).
UIKit provides a set of standard UIBarButtonItems called system items. These happen to include an 'add' item, which is displayed as a plus-sign and used throughout iOS. Using this item solves question 2 and 3.
UIBarButtonItem has a convenience constructor for initialising a system item. See the working example below:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let addProdButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addProduct))
navigationItem.leftBarButtonItem = addProdButton
}
@objc func addProduct() {
print("addProduct() called")
}
}
Selector not working on my swift UIBarButtonItem
Your showSettings:
selector isn't being called because you specified nil
instead of self
for the bar button item's target. Change the line to:
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "modify"), style: UIBarButtonItemStyle.Plain, target: self, action: Selector("showSettings:"))
This assume the showSettings:
method is in the same class that contains this line of code.
Read the documentation for this initializer, specifically the info about the target
parameter.
SWIFT - UIBarButtonItem is not calling action
The problem is that uploadButton
is getting initialized too early, i.e. during the initialization of the view controller ifself. At that point, self
is not yet ready for use.
There are a few ways to solve this.
- Initialize the button in
viewDidLoad
:
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let uploadButton = UIBarButtonItem(title: "UPLOAD", style: .plain, target: self, action: #selector(uploadHandler))
self.navigationItem.setRightBarButton(uploadButton, animated: false)
}
...
}
- If some other methods in your class need access to it, slightly modify the code above by creating an implicitly unwrapped stored property and setting it in
viewDidLoad
:
class MyViewController: UIViewController {
private var uploadButton: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
uploadButton = UIBarButtonItem(title: "UPLOAD", style: .plain, target: self, action: #selector(uploadHandler))
self.navigationItem.setRightBarButton(uploadButton, animated: false)
}
...
}
- Make the initialization of the button lazy, that way it will be initialized when it's first accessed, i.e. in viewDidLoad:
class MyViewController: UIViewController {
private lazy var uploadButton = UIBarButtonItem(title: "UPLOAD", style: .plain, target: self, action: #selector(uploadHandler))
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.setRightBarButton(uploadButton, animated: false)
}
...
}
- Initialize the button without an action and a selector, add them later in
viewDidLoad
:
class MyViewController: UIViewController {
private let uploadButton = UIBarButtonItem(title: "UPLOAD", style: .plain, target: nil, action: nil)
override func viewDidLoad() {
super.viewDidLoad()
uploadButton.target = self
uploadButton.action = #selector(uploadHandler)
self.navigationItem.setRightBarButton(uploadButton, animated: false)
}
...
}
There's very little difference among all these options, so it should be fine whatever one you choose.
A couple of side notes:
- In my examples I declared
uploadButton
as private to indicate that it is not a part of your view controller's public API. If you need to access this button outside of your view controller, just remove theprivate
modificator. - Animation doesn't get performed in
viewDidLoad
because your view is not yet on screen, so callingsetRightBarButton(uploadButton, animated: true)
will not trigger the animation, therefore I replacedtrue
withfalse
. If you want the user to see the animation, call it inviewDidAppear
.
swift 3.0 UIBarButtonItem action not work
Swift 3.0
Declare UIBarButton inside ViewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
let logout: UIBarButtonItem = UIBarButtonItem.init(title: "Logout", style: .plain, target: self, action: #selector(ViewController.logOut))
}
func logOut() {
print("LogOut")
}
Declare UIBarButtonItem OutSide ViewDidLoad()
var logout:UIBarButtonItem = UIBarButtonItem()
override func viewDidLoad() {
super.viewDidLoad()
logout = UIBarButtonItem.init(title: "Logout", style: .plain, target: self, action: #selector(ViewController.logOut))
}
func logOut() {
print("LogOut")
}
Declare Completely Outside viewDidLoad()
lazy var logout: UIBarButtonItem = {
UIBarButtonItem.init(title: "Logout", style: .plain, target: self, action: #selector(ViewController.logOut))
}()
Any Should work.
For your action parameter either you can specify ViewController
name explicitly or you can just say self
.
action: #selector(self.logOut)
UIBarButtonItem Selector Function Not Being Called
Your function is not being called because:
If you use a closure to initialize a property, remember that the rest of the instance has not yet been initialized at the point that the closure is executed. This means that you cannot access any other property values from within your closure, even if those properties have default values.
moreover:
You also cannot use the implicit self property, or call any of the instance’s methods.
to solve this issue (cannot access to self
during the initialization) you might declare such UIBarButtonItem
as lazy var
, so it will be created safely after the ViewController
has been initialized:
lazy var addReminder:UIBarButtonItem = {
return UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(HomePageViewController.addNewReminder))
}()
Related Topics
How to Click a Button Programmatically
Why Is 'Throws' Not Type Safe in Swift
Swipe Animation for Remove Cell in Uicollectionview - Swift 2.0
What Is the Replacement for Isdigit() for Characters in Swift
Swift Access to Variable Length Array
How to Detect and Make Clickable Links in a Uilabel Not Using Uitextview
Swift Can't Infer Generic Type When Generic Type Is Being Passed Through a Parameter
Swift/Firebase - Sort Posts in Tableview by Date
Why Is the Swift Compiler Marking This as an Error
Can't Form Range with End < Start Check Range Before Doing for Loop
How to Mimic 'Uitableviewcontroller' Showing of the Large Titles in 'Navigationbar' on iOS 11
Swift: How to Get Form Values Using Eureka Form Builder
Scngeometryelement Setup in Swift 3
Multiple Enum Types List All Cases
Error: Binary Operator '<=' Cannot Be Applied to Operands of Type 'Int' and 'Int'