That is not a simple rectangle. That is actually a menu to show the navigation stack. It will have more buttons if you navigate deeper. This can’t be get rid of with normal APIs but you can get around it wit some swizzling:
- Implement this:
private func swizzle(
targetClass: AnyClass,
originalSelector: Selector,
swizzledSelector: Selector
) {
let originalMethod = class_getInstanceMethod(targetClass, originalSelector)
let swizzledMethod = class_getInstanceMethod(targetClass, swizzledSelector)
method_exchangeImplementations(originalMethod!, swizzledMethod!)
}
extension UIViewController {
static let classInit: Void = {
let originalSelector = #selector(viewWillAppear(_:))
let swizzledSelector = #selector(swizzledViewWillAppear(_:))
swizzle(
targetClass: UIViewController.self,
originalSelector: originalSelector,
swizzledSelector: swizzledSelector
)
}()
@objc func swizzledViewWillAppear(_ animated: Bool) {
if #available(iOS 14.0, *) {
let backButton = BackBarButtonItem(title: "", style: .plain, target: nil, action: nil)
navigationItem.backBarButtonItem = backButton
}
swizzledViewWillAppear(animated)
}
}
class BackBarButtonItem: UIBarButtonItem {
@available(iOS 14.0, *)
override var menu: UIMenu? {
get { super.menu }
set { }
}
}
- Call
UIViewController.classInitsome where early (like the init of a view):
struct SomeView: View {
init() {
UIViewController.classInit
}
,,,
}

💡 Keep the menu with a workaround
Instead of above method, you can set the correct navigation title name onDisappear to make it work as expected:
struct NavigationTesting: View {
@State var title: LocalizedStringKey = " "
var body: some View {
NavigationStack {
NavigationLink("Next") {
Text("View 2")
}
.navigationTitle(title)
.onDisappear { title = "Page 1" }
.onAppear { title = " " }
}
}
}
This way you can populate the menu with the correct name and keeping the “back” title hidden as intended.





