WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

SOLVED: Day 30 Project 5: navigation Title doesn't show

Forums > 100 Days of SwiftUI

Hi all, I'm walking through Day 30, Part 2 "Running code when our app launches", and unlike what the instruction says, I do not see a random eight-letter word at the top of the navigation view.

Does it happen because .navigationTitle(rootWord) is not working, or onAppear() is not working?

Here is my code.

I have followed every step and couldn't see where went wrong.

import SwiftUI

struct ContentView: View {
    @State private var usedWords = [String]() //an array of words already used
    @State private var rootWord = "" //to spell other words from
    @State private var newWord = "" //a string we can bind to a text field

    var body: some View {
        NavigationView {
            List {

                Section {
                    TextField("Enter your word: ", text: $newWord).autocapitalization(.none)
                }

                Section {
                    ForEach(usedWords, id: \.self) {word in
                        HStack {
                            Image(systemName: "\(word.count).circle.fill")
                            Text(word)
                        }
                    }
                }

            }
        }
        .navigationTitle(rootWord)
        // an alternative way is to write onSubmit(addNewWord), but I find this one to be intuitve
        .onSubmit{
            addNewWord()
        }
        .onAppear(perform: startGame)
    }

    // call this function when the user press return on the keyboard
    func addNewWord() {
        // lowercase and trim the word, to make sure we don't add duplicate words with case differences
        let answer = newWord.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)
        // exit if the remaining string is empty
        guard answer.count > 0 else { return }
        withAnimation {
            usedWords.insert(answer, at: 0) // put it at the beginning of the array
        }
        newWord = ""
    }

    func startGame() {
        // 1. Find the URL for start.txt in our app bundle
        if let startWordsURL = Bundle.main.url(forResource: "start", withExtension: "txt") {
            // 2. Load start.txt into a string
            if let startWords = try? String(contentsOf: startWordsURL) {
                // 3. Split the string up into an array of strings, splitting on line breaks
                let allWords = startWords.components(separatedBy: "\n")

                // 4. Pick one random word, or use "silkworm" as a sensible default
                rootWord = allWords.randomElement() ?? "holyshit"
                // If we are here everything has worked, so we can exit
                return
            }
        }
        // If were are *here* then there was a problem – trigger a crash and report the error
        fatalError("Could not load start.txt from bundle.")
    }

}

   

It look like yo have attached the .navigationTitle(rootWord) to the NavigationView and you need to attach it to a view inside the NavigationView so if you attach it to List it should work.

1      

Yes it worked. I don't exactly understand why though.

   

NavigationView provides a container for a bunch of Views that can be navigated through. The container doesn't have a title itself; the title is supplied by each View that is contained within.

That way, each View you navigate to can have its own title rather than having one title for the entire navigation stack.

It also makes it easy for the back button to display the title of the previous View in the stack. It can hold the stack of previous Views and ask each one for its title when it needs to. Otherwise, the NavigationView would need to separately track all the previous titles in addition to tracking the previous Views.

1      

I will try to explain but think Paul says better in one of his video (not sure which one)

The Navigation Title belongs to the view inside the NavigationView. If you have ContentView that has a link to a SecondView you do not put a NavigationView in the SecondView as it inherits it from the previous view.

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink {
                SecondView()
            } label: {
                Text("Hello, world!")
            }
            .navigationTitle("First View")
        }
    }
}
struct SecondView: View {
    var body: some View {
        VStack {
            Text("Goodbye world!")
        }
        .navigationTitle("Second View")
    }
}

i have just seen @roosterboy has also explained as well hopefully you have a better understanding

   

Thank you both, very helpful. When I work through projects, I like to read the text instead of watching Paul's video. Do you think the video is superior? I remember Paul wrote at the beginning of the 100 day course that there is a content equivalency between those two.

   

I'm having this same problem, but the solution isn't working for me. I was able to confirm that "allWords" is being populated with the word list and a random word is being assigned to "rootWord." Despite this, the navigation title isn't showing up.

I can get a placeholder title to show up, for example .navigationTitle("Title") works.

 var body: some View {
        NavigationView {
            List {
                Section {
                    TextField("Enter your word", text: $newWord)
                        .autocapitalization(.none)
                }

                Section {
                    ForEach(usedWords, id: \.self) { word in
                        HStack {
                            Image(systemName: "\(word.count).circle")
                            Text(word)
                        }
                    }
                }
            }
            .navigationTitle(rootWord)
            .onSubmit(addNewWord)
            .onAppear(perform: startGame)
        }
    }

   

Hacking with Swift is sponsored by Emerge

SPONSORED Why are Swift reference types bad for app startup time, and what’s the performance cost of protocol conformances? That’s just a couple of the topics you can learn about on the Emerge blog — written by the app performance experts behind Emerge’s advanced app optimization and monitoring tools, based on their experience of working at companies like Apple, Airbnb, Snap, and Spotify.

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.