Reputation: 801
I have a BarButtonItem I want to add to every single ViewController in my app. How can I do this without having to copy/paste the button creation code and the action function into each ViewController? I would prefer reusability instead of having the same code in every ViewController.
Button Code:
// Settings button
let btn = UIButton(type: .custom)
btn.setImage(UIImage(named: "icon-settings"), for: .normal)
btn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
btn.addTarget(self, action: #selector(showSettings(sender:)), for: .touchUpInside)
let settingsBtn = UIBarButtonItem(customView: btn)
self.navigationItem.setRightBarButton(settingsBtn, animated: false)
The Action:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "SettingsVC") as! SettingsViewController
self.navigationController?.show(vc, sender: self)
I've tried adding this code to a separate Utility class, but you can't perform the segue from it since there is no way to access the button's parent ViewController from the action function if it is declared in the Utility class. I also tried subclassing UINavigationController and assigning that subclass to the NavigationController in my Storyboard, but it didn't work.
Upvotes: 1
Views: 286
Reputation: 662
You can do this by adding a BaseViewController
and inserting the code there. After that, on your rootviewController of your navigationController, you just extend from this BaseViewController
. Doing that, and calling super
in that function it will always having that code available and you don't need to repeat in every viewcontroller.
import UIKit
class BaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Settings button
let btn = UIButton(type: .custom)
btn.setImage(UIImage(named: "icon-settings"), for: .normal)
btn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
btn.addTarget(self, action: #selector(showSettings(sender:)), for: .touchUpInside)
let settingsBtn = UIBarButtonItem(customView: btn)
self.navigationItem.setRightBarButton(settingsBtn, animated: false)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
And then in your view controller you just extend BaseViewController
class ViewController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
//Button should already appear here
}
Note that ViewController should be your root view controller.
Upvotes: 2