Custom Back buttons in SwiftUI
tl;dr
- use
ToolbarItem(placement: .principal)
to set the title of the screen, to be shown in the navigation bar - use
navigationTitle()
to set the Back button title when a new screen is pushed onto the navigation stack
Standard naming conventions for the "< Back" button
NavigationView
(and before SwiftUI, UINavigationController
) is the cornerstone of iOS development, for apps with a primary-detail arrangement. It has a load of well-known standard behaviours, one of which is the naming of the "< Back" button - which returns the user to the previous screen in the navigation stack.
The rules for naming the "< Back" button are:
- by default, the button title is an arrow "<" followed by the
navigationTitle
of the previous screen - ... unless the title is too long to fit, in which case use the word "Back" instead
This default behaviour works well in most cases, but there are occasions when we want the Back button and navigation title to have different names.
Customisation in UIKit
For a UIKit app, the accepted way of customising the Back button is to set UIViewController.navigationItem.backButtonTitle
:
func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.backButtonTitle = "The previous page"
}
Sometimes, apps will change the ViewController's title in viewDidDisappear
... which isn't great:
func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated: animated)
self.title = "Go baaack"
}
But this post is about SwiftUI, not UIKit.
How not to do it in SwiftUI
There are several blogposts which explain how to do this, which is usually:
- use
.navigationBarBackButtonHidden()
modifier to hide the system Back button - add
@Environment(\.presentationMode) var presentation
to the View, so it can be dismissed in code - add a replacement back button to the navigation bar which performs
self.presentation.wrappedValue.dismiss()
The main problem with this approach is that it removes a lot of the standard Back button behaviour - including the "long press" gesture which shows the titles of all the previous pages in the navigation stack.
Custom Back buttons in SwiftUI
If you're targeting iOS 14 or later, and using .navigationBarTitleDisplayMode(.inline)
, there's a better way:
var body: some View {
NavigationView {
NavigationLink("Press Me", destination: Text("Detail").navigationTitle("Detail View"))
.navigationBarTitleDisplayMode(.inline)
// this sets the Back button text when a new screen is pushed
.navigationTitle("Back to Primary View")
.toolbar {
ToolbarItem(placement: .principal) {
// this sets the screen title in the navigation bar, when the screen is visible
Text("Primary View")
}
}
}
}
This uses the new .toolbar
view modifier in iOS 14. The .principal
placement is the key here. Apple's documentation says:
In iOS, iPadOS, and tvOS, the system places the principal item in the center of the navigation bar. This item takes precedent over a title specified through
View/navigationTitle
.
What does it look like?
I'll be using this technique in a future release of my Nearly Departed app. It currently shows all departures from a UK railway station, and will soon also show details of a single service.
I want to keep the same screen titles ("Departures" and "Service"), but change the name of the Back button so that the "long press" menu shows the actual route names, so the user can accurately go back to a particular screen in the navigation stack.

First published 2 November 2021