问题
In SwiftUI I couldn't find a way to detect when the user taps on the default back button of the navigation view when I am inside DetailView1 in this code:
struct RootView: View {
@State private var showDetails: Bool = false
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: DetailView1(), isActive: $showDetails) {
Text("show DetailView1")
}
}
.navigationBarTitle("RootView")
}
}
}
struct DetailView1: View {
@State private var showDetails: Bool = false
var body: some View {
NavigationLink(destination: DetailView2(), isActive: $showDetails) {
Text("show DetailView2")
}
.navigationBarTitle("DetailView1")
}
}
struct DetailView2: View {
var body: some View {
Text("")
.navigationBarTitle("DetailView2")
}
}
Using .onDisappear doesn't solve the problem as its closure is called when the view is popped off or a new view is pushed.
回答1:
Following up on my comment, I would react to changes in the state of showDetails. Unfortunately didSet doesn't appear to trigger with @State variables. Instead, we can use an observable view model to hold the state, which does allow us to do intercept changes with didSet.
struct RootView: View {
class ViewModel: ObservableObject {
@Published var showDetails = false {
didSet {
debugPrint(showDetails)
// Maybe do something here?
}
}
}
@ObservedObject var viewModel = ViewModel()
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: DetailView1(), isActive: $viewModel.showDetails) {
Text("show DetailView1")
}
}
.navigationBarTitle("RootView")
}
}
}
回答2:
The quick solution is to create a custom back button because right now the framework have not this possibility.
struct DetailView : View {
@Environment(\.presentationMode) var mode: Binding<PresentationMode>
var body : some View {
Text("Detail View")
.navigationBarBackButtonHidden(true)
.navigationBarItems(leading: Button(action : {
self.mode.wrappedValue.dismiss()
}){
Image(systemName: "arrow.left")
})
}
}
回答3:
An even nicer (SwiftUI-ier?) way of observing the published showDetails property:
struct RootView: View {
class ViewModel: ObservableObject {
@Published var showDetails = false
}
@ObservedObject var viewModel = ViewModel()
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: DetailView1(), isActive: $viewModel.showDetails) {
Text("show DetailView1")
}
}
.navigationBarTitle("RootView")
.onReceive(self.viewModel.$showDetails) { isShowing in
debugPrint(isShowing)
// Maybe do something here?
}
}
}
}
来源:https://stackoverflow.com/questions/61930915/swiftui-detecting-the-navigationview-back-button-press