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
CodePudding user response:
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

