簡體   English   中英

SwiftUI:檢測到 NavigationView 后退按鈕按下

[英]SwiftUI: detecting the NavigationView back button press

SwiftUI中,當我在這段代碼中的DetailView1中時,我找不到一種方法來檢測用戶何時點擊導航視圖的默認后退按鈕:

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")
    }
}

使用.onDisappear並不能解決問題,因為在彈出視圖或推送新視圖時會調用它的閉包。

跟進我的評論,我將對showDetails的 state 的更改做出反應。 不幸的是didSet似乎沒有用@State變量觸發。 相反,我們可以使用可觀察視圖 model 來保存 state,這確實允許我們使用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")
        }
    }
}

觀察已發布的showDetails屬性的更好(SwiftUI-ier?)方式:

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?
            }
        }
    }
}

快速的解決方案是創建一個自定義的后退按鈕,因為現在框架沒有這種可能性。

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")
            })
    }
}

按下后退按鈕后,視圖會將 isPresented 設置為 false,因此您可以在該值上使用觀察者來在按下后退按鈕時觸發代碼。 假設此視圖顯示在導航 controller 中:

struct MyView: View {
    @Environment(\.isPresented) var isPresented

    var body: some View {
        Rectangle().onChange(of: isPresented) { newValue in
            if !newValue {
                print("detail view is dismissed")
            }
        }
    }
}
    

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM