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