【问题标题】:List is not propagating updates in DestinationView列表未在 DestinationView 中传播更新
【发布时间】:2021-02-06 18:35:05
【问题描述】:

一旦详细视图完全呈现,时钟将冻结。

如果您将List 替换为ScrollView/VStack,则传播将进行。

struct ContentView: View {

    @State private var clocks = [Date(), Date(), Date()]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(clocks.indices) { idx in
                    NavigationLink(destination: Text(clocks[idx], formatter: formatter)) {
                        Text("Counter \(idx)")
                    }
                }
            }
        }
        .onReceive(Timer.publish(every: 1, on: .main, in: .default).autoconnect()) {
            clocks[0] = $0
            clocks[1] = $0
            clocks[2] = $0
        }
    }
    
    var formatter: DateFormatter {
        let formatter = DateFormatter()
        formatter.timeStyle = .medium
        return formatter
    }
}

【问题讨论】:

    标签: swift swiftui swiftui-list swiftui-navigationview


    【解决方案1】:

    您的目的地 (Text) 只是从 clocks 捕捉静态时刻 (Date),并没有意识到它正在更新。

    为什么这发生在List 而不是ScrollView 有点神秘,但我会假设SwiftUI 正在做一些事情来尝试确定List 行是否是相同,如果它认为不需要重新渲染它们,则不会重新渲染它们,以提高效率,ScrollViewVStack 不这样做。

    这是一个可能的解决方案,它使用 ObservableObject 视图模型在视图之间传递数据并通过 Published 属性保持更新。

    class ViewModel : ObservableObject {
        @Published var time = Date()
        @Published var clocks = [Date(), Date(), Date()]
        
        var cancellable : AnyCancellable?
        
        init() {
            cancellable = Timer.publish(every: 1, on: .main, in: .default)
                .autoconnect()
                .sink { (date) in
                    self.clocks[0] = date
                    self.clocks[1] = date
                    self.clocks[2] = date
                    print(date)
                }
        }
    }
    
    struct ContentView: View {
    
        @ObservedObject var viewModel = ViewModel()
        
        var body: some View {
            NavigationView {
                List {
                    ForEach(viewModel.clocks.indices) { idx in
                        NavigationLink(destination: DetailView(index: idx, viewModel: viewModel)) {
                            Text("Counter \(idx)")
                        }
                    }
                }
            }.navigationViewStyle(StackNavigationViewStyle())
        }
    
    }
    
    struct DetailView : View {
        var index : Int
        @ObservedObject var viewModel : ViewModel
        
        var body: some View {
            Text(viewModel.clocks[index], formatter: formatter)
        }
        
        var formatter: DateFormatter {
                let formatter = DateFormatter()
                formatter.timeStyle = .medium
                return formatter
            }
    }
    

    【讨论】:

    • 恕我直言,将格式化程序设为 static 是一个好习惯 - 每次计算正文时都会重新创建计算属性。可以在此处找到示例:How to format text inside text views.
    • 绝对正确——没有从 OP 的代码中解决这个问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-14
    • 2015-05-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多