119

I am learning SwiftUI using Apple's official tutorial: https://developer.apple.com/tutorials/swiftui/building-lists-and-navigation

Everything works perfectly until I try to show a navigation title on a NavigationView by calling .navigationBarTitle.

I have tried to refresh the live view, restart Xcode, but it still doesn't show up.

Here is my code:

import SwiftUI

struct LandmarkList : View {
    var body: some View {
        NavigationView {
            List(landmarkData) { landmark in
                LandmarkRow(landmark: landmark)
            }
        }
        .navigationBarItem(title: Text("Done"))
        .navigationBarTitle(Text("Landmarks"))
    }
}

#if DEBUG
struct LandmarkList_Previews : PreviewProvider {
    static var previews: some View {
        LandmarkList()
    }
}
#endif

Xcode looks like this:

Screenshot

According to the tutorial, it should show the navigation title but it doesn't in my case.

Any idea why? Thanks!

Adam
  • 2,851
  • 1
  • 20
  • 20
Yiming Dong
  • 1,530
  • 2
  • 9
  • 11

5 Answers5

271

.navigationBarTitle() and .navigationBarItem() are modifiers on the View inside of the NavigationView, not on the NavigationView itself:

struct LandmarkList: View {
    var body: some View {
        NavigationView {
            List(landmarkData) { landmark in
                LandmarkRow(landmark: landmark)
            }
            .navigationBarItem(title: Text("Done"))
            .navigationBarTitle(Text("Landmarks"))
        }
    }
}

and if you think about it, this makes sense. As the View within the NavigationView changes, the new View dictates what the title and contents of the navigation bar should be.

vacawama
  • 150,663
  • 30
  • 266
  • 294
18

Description:

NavigationView is just a container around some content. Contents are changing when you navigating from page to page, but the NavigationView persists.

The point is that NavigationView shows each view's content when it shows it. So it will encapsulate with the destination.

Finally, you should add all navigation modifiers inside the navigation (on the content)

⚠️ From iOS 14+ you should use ToolbarItem instead of navigationBarItem like below


Example:

struct Content: View {
    var body: some View {
        Text("Some. content")

            // iOS 14+
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) { Text("Done") }
            }

            // iOS 13-16.4(deprecated) - You can use toolbar now
            // .navigationBarItems(trailing: Text("Done"))

            .navigationBarTitle(Text("Landmarks"))
    }
}
struct Parent: View {
    var body: some View {
        NavigationView {
            Content() // This contains navigation modifiers inside the view itself
        }
    }
}
Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278
3

If someone is looking for navigation title with tab button, this code may be helpful -

struct ContentView: View {
    var body: some View {
        NavigationView {
            Text("SwiftUI")
                .navigationTitle("Screen Title")
                .toolbar {
                    Button("Right") {
                        print("Right button tapped!")
                    }
                }
        }
    }
}
Anupam Mishra
  • 3,408
  • 5
  • 35
  • 63
0

If you are arriving here and using NavigationStack (in fact NavigationView has a warning for future deprecation since iOS 16), just put the .navigationTitle("My title") modifier on the content of the NavigationStack, not on the NavigationStack itself.

e.g.

var body: some View {
    NavigationStack(path: $path) {
        List {
            [...]
        }
        .navigationTitle("My title")  //    <<-- !! Modifier goes here !!
    }
}
Nikolay Suvandzhiev
  • 8,465
  • 6
  • 41
  • 47
0

.modifier(NavigationView()) had to be added AFTER .navigationBar* modifiers, not before

Anton Tropashko
  • 5,486
  • 5
  • 41
  • 66