Reputation: 36610
I have a somewhat bewildering problem. In my app, I have a toolbar that can swap out buttons programmatically and properly call the associated selector. However, when I apply the same technique to a button on the navigation bar, it fails to call the selector. The following sample code contains 2 sets of buttons (one for nav & one for toolbar). Despite being identical, the selector on the nav bar button is never called.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var toolbar: UIToolbar!
let navCancelButton = UIBarButtonItem(barButtonSystemItem: .cancel,
target: self,
action: #selector(toggleDelete))
let navTrashButton = UIBarButtonItem(barButtonSystemItem: .trash,
target: self,
action: #selector(toggleDelete))
let toolbarCancelButton = UIBarButtonItem(barButtonSystemItem: .cancel,
target: self,
action: #selector(toggleDelete))
let toolbarTrashButton = UIBarButtonItem(barButtonSystemItem: .trash,
target: self,
action: #selector(toggleDelete))
var isDeleting = false {
didSet {
navigationItem.rightBarButtonItem = isDeleting ? navCancelButton : navTrashButton
toolbar.items = isDeleting ? [toolbarCancelButton] : [toolbarTrashButton]
}
}
override func viewDidLoad() {
super.viewDidLoad()
isDeleting = false
}
@objc func toggleDelete() {
isDeleting = !isDeleting
}
}
This shows the previous code in action:
Upvotes: 1
Views: 417
Reputation: 10105
The fact is the target is being lost, it might be a "bug", a possible workaround is using the lazy var
lazy var navCancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(toggleDelete))
lazy var navTrashButton = UIBarButtonItem(barButtonSystemItem: .trash, target: self, action: #selector(toggleDelete))
Upvotes: 4
Reputation: 4711
It appears that the buttons in the nav bar lose their target. So you can either set the target in the viewDidLoad like this:
self.navTrashButton.target = self
self.navCancelButton.target = self
or what I would do is just put the variables in the class scope like this:
var navCancelButton: UIBarButtonItem!
var navTrashButton: UIBarButtonItem!
and then create them in viewDidLoad like this:
navCancelButton = UIBarButtonItem(barButtonSystemItem: .cancel,
target: self,
action: #selector(toggleDelete))
navTrashButton = UIBarButtonItem(barButtonSystemItem: .trash,
target: self,
action: #selector(toggleDelete))
That way you know the buttons are being created when the view controller is expecting them to be and ready for them.
Upvotes: 5