UIBarButtonItem
iOS development
Swift programming
mobile app UI
iOS user interface

How do I show/hide a UIBarButtonItem?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

UIBarButtonItem does not have a direct hidden property, so show and hide behavior is achieved by adding or removing items from navigation or toolbar arrays. The best approach depends on whether you need to preserve layout spacing or simply remove the action temporarily. This guide covers clean, maintainable patterns in Swift.

Show and Hide in a Navigation Bar

For a single right item, assign the property when showing and set it to nil when hiding.

swift
1import UIKit
2
3final class DetailViewController: UIViewController {
4    private lazy var editItemButton = UIBarButtonItem(
5        title: "Edit",
6        style: .plain,
7        target: self,
8        action: #selector(onEditTap)
9    )
10
11    override func viewDidLoad() {
12        super.viewDidLoad()
13        navigationItem.rightBarButtonItem = editItemButton
14    }
15
16    func setEditVisible(_ visible: Bool, animated: Bool = true) {
17        navigationItem.setRightBar(visible ? editItemButton : nil, animated: animated)
18    }
19
20    @objc private func onEditTap() {
21        print("edit tapped")
22    }
23}

This is the simplest and most common pattern.

Managing Multiple Bar Items

If you have multiple actions, store the original item array and restore when needed.

swift
1final class InboxViewController: UIViewController {
2    private var savedRightItems: [UIBarButtonItem] = []
3
4    override func viewDidLoad() {
5        super.viewDidLoad()
6        let filter = UIBarButtonItem(title: "Filter", style: .plain, target: nil, action: nil)
7        let compose = UIBarButtonItem(barButtonSystemItem: .compose, target: nil, action: nil)
8        savedRightItems = [compose, filter]
9        navigationItem.rightBarButtonItems = savedRightItems
10    }
11
12    func hideActions() {
13        navigationItem.rightBarButtonItems = []
14    }
15
16    func showActions() {
17        navigationItem.rightBarButtonItems = savedRightItems
18    }
19}

Keeping a saved copy avoids rebuilding button instances repeatedly.

Preserving Layout with Placeholder Items

Sometimes removing an item causes surrounding title or alignment shifts. In those cases, swap with a disabled placeholder item of similar width.

swift
let placeholder = UIBarButtonItem(title: " ", style: .plain, target: nil, action: nil)
placeholder.isEnabled = false
navigationItem.rightBarButtonItem = placeholder

This technique can keep visual balance during temporary state changes.

Toolbar Item Visibility

For toolbars, use setItems and animate transitions.

swift
1let save = UIBarButtonItem(barButtonSystemItem: .save, target: nil, action: nil)
2let flexible = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
3let trash = UIBarButtonItem(barButtonSystemItem: .trash, target: nil, action: nil)
4
5toolbarItems = [save, flexible, trash]
6navigationController?.isToolbarHidden = false
7
8func toggleTrash(_ visible: Bool) {
9    if visible {
10        toolbarItems = [save, flexible, trash]
11    } else {
12        toolbarItems = [save]
13    }
14    navigationController?.setToolbarHidden(false, animated: true)
15}

Keep toolbar state in one place so updates remain predictable.

State-Driven Visibility

In production apps, button visibility should reflect screen state, permissions, or async task status. Centralize this in one render method:

swift
1func render(canEdit: Bool, isLoading: Bool) {
2    let show = canEdit && !isLoading
3    navigationItem.setRightBar(show ? editItemButton : nil, animated: true)
4}

State-driven rendering prevents scattered UI mutations and race conditions.

Bar button visibility often depends on navigation state, edit mode, and user permissions at the same time. Keep these rules in one state renderer instead of toggling items from many callbacks. Centralized rendering makes transitions easier to reason about and prevents flicker during rapid updates.

For animated transitions, update navigation items inside lifecycle-safe points such as viewWillAppear or explicit state-change handlers on the main thread. This improves consistency during push and pop animations.

Common Pitfalls

A common mistake is creating new button instances every time visibility changes. Repeated creation can lose target-action setup consistency.

Another issue is hiding visually but leaving action paths reachable through other triggers. Ensure UI state and business state stay aligned.

Developers also forget accessibility updates. When actions disappear, verify voice navigation order and announcements still make sense.

Finally, bar item updates must happen on the main thread. Background-thread mutations can lead to intermittent UI issues.

Summary

  • Hide or show UIBarButtonItem by replacing navigation or toolbar item arrays.
  • Use nil assignment for simple single-item visibility toggling.
  • Preserve layout with placeholders only when visual shifts matter.
  • Keep visibility logic state-driven and centralized.
  • Update bar items on the main thread and verify accessibility behavior.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.