Skip to content
Hironobu Iga

Hiding the back button's text in SwiftUI

Hiding it with navigationBarBackButtonHidden also costs you the swipe-back gesture and the long-press stack. Adjusting UINavigationBar's appearance is the safer route.

Published

This article is also published elsewhere. https://iganin.hatenablog.com/entry/2024/02/26/201210

Originally written in Japanese. This is a translation of the same piece.

This feels like well-trodden ground, but I looked into it again, so here are my notes.

TL;DR

  • You can do it by adjusting UINavigationBar’s appearance
  • Setting navigationBarBackButtonHidden and adding a navigation item to navigationBarLeading also works, but you lose the following:
    • Navigating back to the previous screen with the swipe gesture
    • Long-pressing the back button to show the stack and jump to a screen from it

Environment

Verified on:

  • iOS 17.x
  • Xcode 15.2

UIKit

First, how to do it in UIKit. This one is very easy: set navigationItem.backButtonDisplayMode to minimal. It requires iOS 14 or later, but these days that deployment target is usually already met.

backButtonDisplayMode | Apple Developer Documentation

SwiftUI

Now for SwiftUI.

Adjusting UINavigationBar’s appearance

This is probably the soundest approach. The following hides the back button’s text:

appearance.backButtonAppearance.normal.titleTextAttributes = [.foregroundColor: UIColor.clear]

With this approach you keep the default behaviours that the alternative below disables:

  • Navigating between screens with the swipe gesture
  • Long-pressing to show the stack and navigate to a chosen screen

ToolbarItem(placement: .navigationBarLeading)

Hide the back button with navigationBarBackButtonHidden() and place your own back button using ToolbarItem(placement: .navigationBarLeading). Writing a ViewModifier like the following makes it much less work to apply.

struct MinimalNavigationBarBackButton: ViewModifier {
  @Environment(\.dismiss) var dismiss

  public func body(content: Content) -> some View {
    content
      .navigationBarBackButtonHidden(true)
      .toolbar {
        ToolbarItem(placement: .navigationBarLeading) {
            Button {
                dismiss()
            } label: {
                Image(systemName: "chevron.backward")
            }
            .foregroundStyle(Color.black)
        }
      }
  }
}

It is the intuitive approach, but it disables these defaults:

  • A. Navigating back to the previous screen with a swipe
  • B. Long-pressing the back button to show the stack and navigate to a chosen entry

A can be implemented by adjusting UINavigationController, but applying it globally means you can swipe back even where the back button is hidden, so it needs some control. B is probably implementable too, but looks like more effort.

extension UINavigationController: UIGestureRecognizerDelegate {
    override open func viewDidLoad() {
        super.viewDidLoad()
        interactivePopGestureRecognizer?.delegate = self
    }

    public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return viewControllers.count > 1
    }
}

Other options

These are worth considering as well, though they look likely to change behaviour beyond the back button, so that would need thinking through:

  • Setting the user’s navigationTitle to an empty string at the same time as the transition
  • Specifying editor for toolbarRole

Reference