【问题标题】:ObservedObject not working on NavigationLink's destination if there are updates on parent如果父项有更新,ObservedObject 无法在 NavigationLink 的目的地上工作
【发布时间】:2020-03-06 13:01:17
【问题描述】:

我有两个屏幕,一个 master 和一个 detail,detail 有一个 ObservedObject 有它的状态。我还想隐藏 master 上的导航栏并详细显示它。为此,我将导航栏隐藏状态作为主视图上的 @State 属性,并将其作为绑定变量发送回详细视图。

我遇到的问题是,每当我在详细信息屏幕中更新该变量时,ObservedObject 就会停止工作。

这是重现问题的示例代码:

struct ContentView: View {
    @State var navigationBarHidden = true

    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: DetailView(navigationBarHidden: $navigationBarHidden)) {
                    Text("Go Forward")
                }
            }
            .navigationBarTitle("", displayMode: .inline)
            .navigationBarHidden(navigationBarHidden)
            .onAppear { self.navigationBarHidden = true }
        }
    }
}

class DetailViewModel: ObservableObject {
    @Published var text = "Didn't work"
}

struct DetailView: View {
    @Binding var navigationBarHidden: Bool
    @ObservedObject var viewModel = DetailViewModel()

    var body: some View {
        VStack {
            Text(viewModel.text)
        }.onAppear {
            self.navigationBarHidden = false
            self.viewModel.text = "Worked"
        }
    }
}

如果我保持原样,文本将不会更新为“工作”。如果我删除self.navigationBarHidden = false 行,ObservedObject 将正常工作并且文本将更新。

如何实现预期行为,更新导航栏,同时保持观察到的对象正常工作?

【问题讨论】:

    标签: ios swift swiftui ios-navigationview observableobject


    【解决方案1】:

    原因是,

    NavigationLink(destination: DetailView(navigationBarHidden: $navigationBarHidden)) {
        Text("Go Forward")
    }
    

    激活时创建新的DetailView等新的DetailViewModel

    试试

    import SwiftUI
    
    struct ContentView: View {
        @State var navigationBarHidden = true
        @ObservedObject var viewModel = DetailViewModel()
        var body: some View {
            NavigationView {
                VStack {
                    NavigationLink(destination: DetailView(navigationBarHidden: $navigationBarHidden).environmentObject(viewModel)) {
                        Text("Go Forward")
                    }
                }
                .navigationBarTitle("", displayMode: .inline)
                .navigationBarHidden(navigationBarHidden)
                .onAppear { self.navigationBarHidden = true }
            }
        }
    }
    
    class DetailViewModel: ObservableObject {
        @Published var text = "Didn't work"
    }
    
    struct DetailView: View {
        @Binding var navigationBarHidden: Bool
        @EnvironmentObject var viewModel: DetailViewModel
    
        var body: some View {
            VStack {
                Text(viewModel.text)
            }.onAppear {
                self.navigationBarHidden = false
                self.viewModel.text = "Worked"
            }
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    

    现在您与 DetailView 共享模型,它按预期工作(编写)

    如果我删除 self.navigationBarHidden = false 行,则 ObservedObject 将正常工作,文本将更新。

    如果删除此行,则未重新创建 DetailView(View 中没有任何更改)状态不是 View 状态的一部分,它是引用类型,因此 SwiftUI 在某些值被包装之前不会看到任何更改他们改变了。

    【讨论】:

    • 您已将 environmentObject 添加到 NavigationLink。是否有 WWDC 视频或任何说明您需要这样做的文档?我不争辩这是答案,但我一直被困在这个问题上,解决方案不容易找到
    • @Des 查看公共 func environmentObject(_ bindable: B) 的文档 -> some View where B : ObservableObject
    • @Des 当然还有其他方法可以达到同样的效果
    猜你喜欢
    • 2021-12-05
    • 1970-01-01
    • 2020-08-26
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 2021-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多