0

In a NavigationView, when selecting a different destination, this destination view calls onAppear as expected. However the onDisappear is not called as another destination is selected, at least not immediately, only after a third destination gets selected (see log output below).

struct DetailModel: Identifiable {
    var title: String
    
    var id: String  {
        title
    }
}

struct ContentView: View {
    
    @State var details = [DetailModel(title:"one"), DetailModel(title:"two"), DetailModel(title:"three"), DetailModel(title:"four")]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(details) { detail in
                    NavigationLink(detail.title) {
                        DetailView(detail: detail)
                    }
                }
            }
            .navigationTitle("Details")
        }
    }
}

struct DetailView: View {
    
    var detail: DetailModel
    
    var body: some View {
        Text("DetailView: \(detail.title)")
            .onAppear() {
                print("DetailView: onAppear: \(detail.title)")
            }
            .onDisappear() {
                print("DetailView: onDisappear: \(detail.title)")
            }
    }
}

Log output (extra line between tap events)

DetailView: onAppear: one

DetailView: onAppear: two

DetailView: onDisappear: one
DetailView: onAppear: three

DetailView: onDisappear: two
DetailView: onAppear: four

onDisappear for first detail view only gets called after the second and the third view have been selected.

I understand SwiftUI tries to keep the views for better display performance.

How can I detect that a view is no longer shown so I can perform some action (e.g. pause a video player)?

iOS 15.6 for iPad, XCode 14.0.1, Swift 5

enter image description here

Fred Klein
  • 448
  • 6
  • 13

1 Answers1

2

You can try adding .isDetailLink(true) to your NavigationLink, works for me, in activating the .onAppear and .onDisappear as expected.

Note NavigationView is deprecated, use the recommended NavigationStack when you decide to upgrade to ios-16+

  • Thank you so much! My hero! Interesting enough the documentation says "If you do not set the detail link behavior with this method, the behavior defaults to true". Well it seems this isn't correct, as we have to explicitly set it to true. And yes, checked that migration to NavigationStack. Thanks. – Fred Klein Oct 30 '22 at 10:40
  • hmm, does not seem to work as expected on iOS 15.7 real device. Works like a charm on iOS 16 iPad mini simulator. – Fred Klein Oct 30 '22 at 11:13