Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call onAppear on NavigationView when getting back from child view?

Tags:

swiftui

How do I make NavigationView call onAppear()(or any other functions) whenever it appears, especially when I back out from its child view?

I linked 3 NavigationViews in this way: TestView -> SecondView -> ThirdView, and I put onAppear() function on TestView and SecondView.

struct TestView: View {
    @State var text:String = "This is page 1"
    
    var body: some View {
        NavigationView {
            VStack {
                Text(text)

                NavigationLink(
                    destination: SecondView(),
                    label: { Text("go to page2") }
                )
            }
        }
        .onAppear() {
            text += " called+1 "
        }
    }
}

struct SecondView: View {
    @State var text:String = "This is page 2"
    
    var body: some View {
        NavigationView {
            VStack {
                Text(text)

                NavigationLink(
                    destination: ThirdView(),
                    label: { Text("go to page3") }
                )
            }
        }
        .onAppear() {
            text += " called+1 "
        }
    }
}

struct ThirdView: View {
    var body: some View {
        Text("This is page 3")
    }
}

From the function name onAppear(), I thought it would be invoked every time the view appears. However, it turns out it will only be invoked once when I go deeper into a new view, but NOT invoked when I back out from its child view.

In other words, when the app launches, TestView's onAppear() will be called. Then, when I click go to page2, SecondView's onAppear() will be called. Then I click go to page3, and then I click the back button on the ThirdView, SecondView's onAppear() will bot be invoked, even though the current view is SecondView. And it is the same when I click back on the SecondView, the TestView's onAppear() is not invoked again.

How to call onAppear() when I click Back, or used other method to achieve the same result.

like image 445
BlowMyMind Avatar asked Sep 02 '25 06:09

BlowMyMind


1 Answers

You could try this approach, moving the TestView, .onAppear {..} to the VStack{..} as shown in the example code. Also there is no need for the SecondView NavigationView. With these changes all .onAppear {..} work well for me.

Note that NavigationView is deprecated, use the NavigationStack instead.

struct ContentView: View {
    var body: some View {
        TestView()
    }
}

struct TestView: View {
    @State var text:String = "This is page 1"
    
    var body: some View {
        NavigationView {
            VStack {
                Text(text)
                NavigationLink(destination: SecondView(), label: { Text("go to page2") })
            }
            .onAppear {
                text += " called+1 "
                print("\n------> TestView onAppear ")
            }
        }
    }
}

struct SecondView: View {
    @State var text: String = "This is page 2"
    
    var body: some View {
        VStack {
            Text(text)
            NavigationLink(destination: ThirdView(),label: { Text("go to page3") })
        }
        .onAppear {
            text += " called+1 "
            print("\n------> SecondView onAppear ")
        }
    }
}

struct ThirdView: View {
    var body: some View {
        Text("This is page 3")
    }
}
like image 141
workingdog support Ukraine Avatar answered Sep 05 '25 00:09

workingdog support Ukraine