首页 > 解决方案 > List 中的 ForEach 停止 DestinationView 中的更新传播

问题描述

我认为从这个虚拟示例中非常清楚:如果您删除ForEach代码行,神奇地,传播将流动并且时钟将滴答作响,否则一旦出现详细视图,它将冻结。

class ModelView: ObservableObject {
    @Published var clock = Date()
    init() {
        Timer.publish(every: 1, on: .main, in: .default)
            .autoconnect()
            .print()
            .assign(to: &$clock)
    }
}

struct ContentView: View {

    @StateObject var viewModel = ModelView()
    
    var body: some View {
        NavigationView {
            List {
                NavigationLink("Clock", destination: Text(viewModel.clock, formatter: formatter))
                ForEach(0..<1) { _ in } // <- Remove this row and the clock will work
            }
        }
    }
    
    var formatter: DateFormatter {
        let formatter = DateFormatter()
        formatter.timeStyle = .medium
        return formatter
    }
}

标签: swiftswiftuiswiftui-listswiftui-navigationlinkswiftui-navigationview

解决方案


我想说它在第一种情况下起作用是一种巧合,因为目的地是(或可以)在导航上复制的(这可能发生在第二种情况下)。

正确的方法是与自己的观察者分开独立视图以获取详细信息。如果没有绑定,父视图不应更新子视图属性。

测试并使用 Xcode 12.4 / iOS 14.4

struct ContentView: View {

    @StateObject var viewModel = ModelView()
    
    var body: some View {
        NavigationView {
            List {
                NavigationLink("Clock", destination: DetailsView(viewModel: viewModel))
                ForEach(0..<1) { _ in } // <- Remove this row and the clock will work
            }
        }
    }
    
}

struct DetailsView: View {
    @ObservedObject var viewModel: ModelView
    
    var body: some View {
        Text(viewModel.clock, formatter: formatter)
    }

    var formatter: DateFormatter {
        let formatter = DateFormatter()
        formatter.timeStyle = .medium
        return formatter
    }
}

推荐阅读