Swift - Add same navigation bar items to every page

Related searches

I am trying to add the same navigation bar items to every tab in my application. I currently have them set up correctly in my homeController, but I want to move the code to a separate file and remotely implement it wherever I want.

For example: adding a [search] icon to the left side of the navigation bar without having to use the same code in every swift file.

I don't know whether I should create an enum, protocol or class. What is the best way to do this?

let menuButton = UIButton(type: UIButtonType.system)
menuButton.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
menuButton.addTarget(self, action: #selector(openSearch), for: .touchUpInside)
menuButton.setImage(UIImage(named: "icon_search"), for: UIControlState())
let menuBarButtonItem = UIBarButtonItem(customView: menuButton)

navigationItem.leftBarButtonItems = [menuBarButtonItem]

func openSearch() {
 // Some code

My recommended approach to this would be to create a base view controller class and make all your individual view controllers inheirit from this rather than directly from UIViewController.

Whilst you could do a quick and dirty extension as Umair suggests, this isn't practical for other applications whereas a base view controller allows you to basically add functionality/customise appearance of any aspect of all view controllers within your app.

Here is some example code:

class BaseViewController: UIViewController {
    override func viewDidLoad() {
        let menuButton = UIButton(type: UIButtonType.system)
        menuButton.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
        menuButton.addTarget(self, action: #selector(openSearch), for:    .touchUpInside)
        menuButton.setImage(UIImage(named: "icon_search"), for: UIControlState())
        let menuBarButtonItem = UIBarButtonItem(customView: menuButton)

        navigationItem.leftBarButtonItems = [menuBarButtonItem

    func openSearch() {


Then for all view controllers in your app, just make the declaration:

class SomeRandomViewController: BaseViewController { }


As correctly pointed out in the comments, you will have to do this in every base class. (UIViewController, UITableViewController, UITabViewController etc...) There is a way around this but it is often considered one of the dark arts of the Objective-C runtime. I am of course talking about method swizzling. The following code essentially swaps the implemetations of UIViewController's viewWillAppear: and a custom method. It is totally safe if done correctly, and a correct implementation is shown below.

extension UIViewController {
    public override class func initialize() {
        struct Static {
            static var token: dispatch_once_t = 0

        // make sure this isn't a subclass
        if self !== UIViewController.self {

        dispatch_once(&Static.token) {
            let originalSelector = Selector("viewWillAppear:")
            let swizzledSelector = Selector("extended_viewWillAppear:")

            let originalMethod = class_getInstanceMethod(self, originalSelector)
            let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)

            let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))

            if didAddMethod {
                class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
            } else {
                method_exchangeImplementations(originalMethod, swizzledMethod)

    // MARK: - Method Swizzling

    func extended_viewWillAppear(animated: Bool) {

        // Call your code here that you want to run for all view controllers, table view controllers, tab view controllers etc...

Some developers can't stand the above concept, and you should be aware that it could potentially change in a future release of iOS and break. That said, it won't get your app rejected as it is an actual programming technique.

How to add a bar button to a navigation bar, Was this page useful? Let us know! 1, 2, 3, 4, 5. Average rating: 4.2/� The navigationBarItems () modifier lets us add single or multiple bar button items to the leading and trailing edge of a navigation view. These might be tappable buttons, but there are no restrictions – you can add any sort of view. For example, this adds a single Help button the to trailing edge of a navigation view: var body: some View { NavigationView { Text("SwiftUI") .navigationBarTitle("Welcome") .navigationBarItems(trailing: Button("Help") { print("Help tapped!")

For Swift 4

You Can Use it Very Easily by making an extension of UIViewController

extension UIViewController {

func setupRemainingNavItems() {
    self.navigationController?.setNavigationBarHidden(false, animated: true)
    navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
    navigationController?.navigationBar.shadowImage = UIImage()
    let titleImageView = UIImageView(image: #imageLiteral(resourceName: "your-icon"))
    titleImageView.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
    titleImageView.contentMode = .scaleAspectFit
    titleImageView.clipsToBounds = true
    navigationItem.titleView = titleImageView

    let button = UIButton(type: .custom)
    button.setImage(UIImage (named: "Group 6"), for: .normal)
    button.frame = CGRect(x: 0.0, y: 0.0, width: 30.0, height: 30.0)
    button.addTarget(self, action: #selector(tapbutton), for: .touchUpInside)
    let barButtonItem = UIBarButtonItem(customView: button)

    self.navigationItem.leftBarButtonItem = barButtonItem

@objc func tapbutton(){
    self.navigationController?.popViewController(animated: true)



call it in ViewDidLoad()


Updated code for Swift 5

Firstly declare some variable globally,

 let window = UIApplication.shared.keyWindow

 let topPadding = window?.safeAreaInsets.top

 let bottomPadding = window?.safeAreaInsets.bottom

 let guide = window?.safeAreaLayoutGuide

 let height = guide?.layoutFrame.size.height

 let safeAreaWidth = guide?.layoutFrame.size.width

 let width = UIScreen.main.bounds.width/4

 let parentView = UIView(frame: CGRect(x: 0 , y:( UIScreen.main.bounds.height - 65) - bottomPadding!   , width: safeAreaWidth!, height: 65))

 let blurparentView = UIView(frame: CGRect(x: 0, y: 0, width: safeAreaWidth!, height: 60))

 let backImage = UIImageView(frame: CGRect(x: 7.5 , y: 20, width: 20, height: 20))

 let cartImage = UIImageView(frame: CGRect(x: 6.5 , y: 16.5, width: 25, height: 27))

 let cartLabel = UILabel(frame: CGRect(x: 14, y: -4, width: 14, height: 14))

 let lblWidth = UIScreen.main.bounds.width/2

 extension UIViewController {

 func navigationBarDesign() {

       let parentView = UIView(frame: CGRect(x: 0, y: topPadding!, width: safeAreaWidth!, height: 60))
       parentView.backgroundColor = hexStringToUIColor(hex: Colors.appColor)
       let back = UIView(frame: CGRect(x: 10, y: 0, width: 40, height: 60))
       let title = UIView(frame: CGRect(x: lblWidth - lblWidth/2, y: 0, width: lblWidth, height: 60))
       let cart = UIView(frame: CGRect(x: UIScreen.main.bounds.width - 50, y: 0, width: 40, height: 60))

       blurparentView.backgroundColor = hexStringToUIColor(hex: Colors.blackColor)
       backImage.image = #imageLiteral(resourceName: "Your-Icon")
       cartImage.image = #imageLiteral(resourceName: "Your-Icon")

       let titlelabel = UILabel(frame: CGRect(x: 0, y: 0, width: lblWidth, height: 60))
       titlelabel.font = UIFont(name: "Segoe UI", size: 20.0)
       titlelabel.text = "Home"
       titlelabel.textAlignment = .center
       titlelabel.textColor = .black

       let backButton = UIButton(frame: CGRect(x: 0, y: 0, width: width, height: 50))
       let cartButton = UIButton(frame: CGRect(x: 0, y: 0, width: width, height: 50))

       cartLabel.textAlignment = .center
       cartLabel.textColor = .white
       cartLabel.font = UIFont.boldSystemFont(ofSize: 8.0)
       cartLabel.backgroundColor = hexStringToUIColor(hex: Colors.yellowColor)
       cartLabel.isHidden = false
       backButton.addTarget(self, action: #selector(clickBack), for: .touchUpInside)
      // cartButton.addTarget(self, action: #selector(clickCart), for: .touchUpInside)





       blurparentView.isHidden = true


   @objc func clickBack(){

       parentView.isHidden = false
       navigationController?.popViewController(animated: false)



call it in ViewDidLoad()


How to add multiple UIBarButtonItem to a navigation bar using , One confusion when working with arrays of bar button items is the order in For example, here's some code to display a share button and an add button on the right-hand side of the navigation bar, and Sponsor Hacking with Swift and reach the world's largest Swift community! Was this page useful? Adding Navigation Bar programmatically iOS using Swift iOS iPhone/iPad Mobile Development To add navigation bar programmatically we’ll go through a series of steps that are mentioned below.

For those in future

If subclassing and hardcoding buttons is not your way here is my solution:

  1. Add desired buttons to navigation bar in Storyboard
  2. Connect outlets/actions to your TabBarController
  3. Assuming your flow is TabBarController --> NavigationController --> tab1/tab2/tab3 in viewDidLoad() of TabBarController add:
override func viewDidLoad() {
    if let viewControllers = viewControllers {
        for nvc in viewControllers.compactMap({$0 as? UINavigationController}) {
            let left = navigationItem.leftBarButtonItem
            let right = navigationItem.rightBarButtonItem
            nvc.navigationBar.topItem?.title = "Common Title"
            nvc.navigationBar.topItem?.leftBarButtonItem = left
            nvc.navigationBar.topItem?.rightBarButtonItem = right

UINavigationBar, Swift; Objective-C On This Page To add a navigation bar to your interface, the following steps are required: The default navigation item uses the view controller's title, but you can override the navigationItem on To internationalize navigation bars, specify a localized string for each of the displayed string properties of� Adding bar button items We can add both leading and trailing buttons to a navigation view, using either one or several on either or both sides. These can be standard button views if you want, but you can also use navigation links. For example, this creates one trailing navigation bar button that modifies a score value when tapped:

Customizing Your App's Navigation Bar, Create custom titles, prompts, and buttons in your app's navigation bar. bar's style, or UIBarStyle , by tapping the “Style” button to the left of the main page. The sample also shows how to create and add each button type using code. NSLocalizedString("Duplicate", comment: ""), image: UIImage(systemName:� Deepulu1984 Do i have to copy the same code on every page or is there any other procedure. If you are using MVC or .Net Core then you can make use of layout page.Create the navbar in layout page.

Ability to keep same navigation bar (with Bar Button Item) on , I tried to add a Navigation Bar to a View Controller that isn't the Root View Controller of the Menu Navigation Controller, but it just added another� 14 Swift - Add same navigation bar items to every page Nov 24 '16 14 aps-environment is always development Feb 17 '17 12 Swift 3 warning: Non-optional expression of type 'String' used in a check for optionals Nov 30 '16

Open up a new single view project named NavBarDemo using Swift as the language and Universal device. Go to the storyboard and click the view controller icon in the scene. In the drop down menu, select Editor>Embed in>Navigation controller. Drag two buttons, one labeled Pizza and the other labeled Pasta out to the scene.

  • Do you want to have different button actions on every screen or exactly the same everywhere?
  • The same button actions on every screen.
  • May be you should try to use UINavigationController with built-in navigation bar.
  • How should I deal with the fact that some controllers in my application are UITableViewControllers or even UICollectionViewControllers. This would create a lot of inheritance errors.
  • @DennisvanMazijk Yes that is the only downside. UITableViewController does not inherit from UIViewController so will not automatically gain this functionality. You would need to create a similar thing for UITableViewController and indeed UICollectionViewController as well. It's not ideal but is widely regarded as the correct/best way of achieving this functionality nonetheless. It is the proper OO approach.
  • Thank you. I understand the solution, so I will see how I can adjust my code to make it work.