Pass a selector into an an extension - ios

I am trying to tidy up a ViewController and would like to move the setup of a navigation item to an extension.
This is the code I am looking to move out of the ViewController:
private func setupNavigationItem() {
navigationItem.leftBarButtonItem = UIBarButtonItem.stashWhite(barButtonSystemItem: .cancel, target: self, selector: #selector(cancelBarButtonHandler))
navigationItem.rightBarButtonItem = UIBarButtonItem.stashRed(barButtonSystemItem: .save, target: self, selector: #selector(saveBarButtonItemHandler))
navigationItem.rightBarButtonItem?.isEnabled = false
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
I have then created this extension.
extension UINavigationItem {
func addSavingSetup(_ cancelBarButtonHandler: Selector, _ saveBarButtonItemHandler: Selector) {
leftBarButtonItem = UIBarButtonItem.stashWhite(barButtonSystemItem: .cancel, target: self, selector: cancelBarButtonHandler)
rightBarButtonItem = UIBarButtonItem.stashRed(barButtonSystemItem: .save, target: self, selector: saveBarButtonItemHandler)
rightBarButtonItem?.isEnabled = false
backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
}
I then call it like so:
navigationItem.addSavingSetup(#selector(cancelBarButtonHandler(_:)), #selector(saveBarButtonItemHandler))
However I then get this error when tapping either the cancel or save bar button:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UINavigationItem cancelBarButtonHandler:]: unrecognized selector sent to instance 0x105e01e80
Any idea how I can solve this? Not sure how else to pass in the selector.
Thanks

You are setting different target. you need to pass target, like below
extension UINavigationItem {
func addSavingSetup(target: Any,_ cancelBarButtonHandler: Selector, _ saveBarButtonItemHandler: Selector) {
leftBarButtonItem = UIBarButtonItem.stashWhite(barButtonSystemItem: .cancel, target: target, selector: cancelBarButtonHandler)
rightBarButtonItem = UIBarButtonItem.stashRed(barButtonSystemItem: .save, target: target, selector: saveBarButtonItemHandler)
rightBarButtonItem?.isEnabled = false
backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
}

Related

Swift - #selector methods not being called

I have UIBarButtonItem and the selector method is not being called, been driving me nuts for days.
These are in my viewDidLoad method
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: nil, action: #selector(self.doneButtonPressed))
self.navigationItem.rightBarButtonItem = doneButton
let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: nil, action: #selector(self.cancelButtonPressed))
self.navigationItem.leftBarButtonItem = cancelButton
and here are the methods:
#objc func doneButtonPressed()
{
dismiss(animated: true, completion: nil)
}
#objc func cancelButtonPressed()
{
dismiss(animated: true, completion: nil)
}
How come they are not being called?
You should set target to self instead of nil
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(self.doneButtonPressed))
You need to set a valid target in UIBarButtonItem(title:style:target:action:).
This is how it works behind the scenes: #selector transforms your selector into a Selector type: something that is almost – but not quite – a string. The Objective C runtime later uses that Selector to send a message with the Selector as its content to target; i.e. it calls the selector on the target.
Therefore, you must add the #objc annotation to your target and you must add the target to the constructor.

Unable to change backBarButtonItem in Swift

I want to make my backBarButtonItem to be only < , without back. I have searched stackOverflow and found some solutions, but it stays < back.
I tried this in my pushed VC:
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
and also this, in my AppDelegate:
navigationController.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
But none of two helped me. Anyone knows why?
This is how I push my ViewControllers:
let VC = XYZViewController()
self.navigationController?.pushViewController(VC, animated: true)
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
Write this piece of code in the controller from which you are pushing to the next controller

Why does UIButton target only work when selector is declared in a certain way

I am really confused as to why the follow only works when I create the UIButton in view did load, Im hoping to get an answer to this because im trying to clean my the viewDidLoad function.
let logoutButton: UIBarButtonItem = {
let button = UIBarButtonItem(title: "Logout", style: .plain, target: self, action: #selector(handleLogout))
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = logoutButton // Does not work
// navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Logout", style: .plain, target: self, action: #selector(handleLogout))
}

Hide back button in tabbar navigation controller

I need to hide the Back that is overlapping with Cart
Edit 1
I have already added these things
override func viewWillAppear(animated: Bool) {
super.viewDidAppear(animated)
self.tabBarController!.navigationItem.title = "Orders"
// self.navigationItem.rightBarButtonItem = UIBarButtonItem(title:"Cart", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
self.tabBarController!.navigationItem.rightBarButtonItem = UIBarButtonItem(title:"Cart", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
self.tabBarController!.navigationItem.leftBarButtonItem = UIBarButtonItem(title:"Cart", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
self.navigationItem.hidesBackButton = true
}
override func viewDidLoad() {
super.viewDidLoad()
self.tabBarController!.navigationItem.title = "Orders"
self.navigationItem.title = "Order History"
// self.navigationItem.rightBarButtonItem = UIBarButtonItem(title:"Cart", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
self.tabBarController!.navigationItem.rightBarButtonItem = UIBarButtonItem(title:"Cart", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
self.tabBarController!.navigationItem.leftBarButtonItem = UIBarButtonItem(title:"Cart", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
// Do any additional setup after loading the view.
self.navigationItem.hidesBackButton = true
}
in this place
self.navigationItem.hidesBackButton = true
try this
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: UIView())
option-2
self.tabbarcontroller.navigationcontroller.navigationitem.hidesBackButton = true
self.tabBarController!.navigationItem.rightBarButtonItem = UIBarButtonItem(title:"Cart", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
self.tabBarController!.navigationItem.leftBarButtonItem = UIBarButtonItem(title:"Cart", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
self.navigationItem.hidesBackButton = YES;
Try with below code, write this code on view controller which appear after 1st navigationcontroller ( PushViewController ).
self.navigationItem.setHidesBackButton(true, animated: false)
self.tabBarController!.navigationItem.hidesBackButton = true

Why setting the barItems is not working?

I have a UIViewController, and I embed it into a UINavigationController.
I want to show one item in the toolbar (and by toolbar, I mean this:
This is my code in viewDidLoad method
self.navigationController?.toolbarHidden = false
self.navigationController?.toolbar.items?.append(UIBarButtonItem(title: "Buy Potato", style: .Plain, target: self, action: #selector(ViewController.buyPotato)))
self.navigationController?.toolbarItems?.append(UIBarButtonItem(title: "Buy Potato", style: .Plain, target: self, action: #selector(ViewController.buyPotato)))
self.toolbarItems?.append(UIBarButtonItem(title: "Buy Potato", style: .Plain, target: self, action: #selector(ViewController.buyPotato)))
and I already have the method buyPotato
func buyPotato() {
}
as you see, I tried to do that using either the viewController or the navigationController, but it doesn't work.
All I can see is the toolbar at the bottom of my screen but without any button.
self.navigationController?.toolbarHidden = false
var items = [UIBarButtonItem]()
items.append(
UIBarButtonItem(barButtonSystemItem: .Plain, target: self, action: nil))
items.append(
UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "onClickedToolbeltButton:"))
self.setToolbarItems(barButtonItems, animated: true)
This has to work for you as per the answer written here.
Delete
self.setToolbarItems(barButtonItems, animated: true)
Add
self.toolbarItems = barButtonItems

Resources