SwiftUI: detecting the NavigationView back button press

孤街醉人 提交于 2021-01-07 03:01:48

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!