SwiftUI NavigationView双栏动态列表右栏数据不实时刷新问题
问题原因
右栏无法实时刷新的核心问题是状态声明使用错误:DataProvider是引用类型的ObservableObject,@Binding只能感知绑定值本身的替换(比如切换选中其他左栏条目时,选中实例被替换,右栏会刷新),但无法订阅实例内部@Published属性的变化。修改选中条目内部的子列表时,实例引用地址没有变化,@Binding不会触发右栏视图更新。
修改方案
只需要做两处最小改动即可实现实时刷新,不需要重构现有数据源逻辑:
- 将
RightPane中的@Binding var dataProvider: DataProvider?替换为@ObservedObject var dataProvider: DataProvider?。@ObservedObject会自动订阅ObservableObject实例的所有@Published属性变化,内部数据更新时会主动触发视图重绘。 - 调整
LeftPane中调用RightPane的传参方式,去掉$符号,直接传入选中的实例而非Binding引用,因为右栏不需要修改选中状态,只需要读取并观察选中实例的内容。
修改后完整可运行代码
// // DemoApp.swift // Shared // // Created by Fred Appelman on 08/06/2022. // import SwiftUI @main struct DemoApp: App { var body: some Scene { WindowGroup { LeftPane() } } } class DataProvider: ObservableObject, Identifiable, Hashable { static func == (lhs: DataProvider, rhs: DataProvider) -> Bool { lhs.id == rhs.id } func hash(into hasher: inout Hasher) { hasher.combine(id) } let id = UUID() @Published var name: String @Published var data: [DataProvider] init(name: String, data: [DataProvider]) { self.name = name self.data = data } } struct RightPane: View { @ObservedObject var dataProvider: DataProvider? var body: some View { if let dataProvider = dataProvider { List(dataProvider.data, id: \.self) { item in Text(item.name) } } else { Text("Select in left pane") } } } struct LeftPane: View { @State var data: [DataProvider] = [ DataProvider(name: "left-a", data: [ DataProvider(name: "right-a1", data: []), DataProvider(name: "right-a2", data: []) ]), DataProvider(name: "left-b", data: [ DataProvider(name: "right-b1", data: []), DataProvider(name: "right-b2", data: []) ]), ] @State private var selectedProvider: DataProvider? var body: some View { NavigationView { List(data, id: \.self, selection: $selectedProvider) { element in Text(element.name) } RightPane(dataProvider: selectedProvider) } Button("Add extra data") { let extraDataLeftPane = DataProvider(name: "left-c", data: [ DataProvider(name: "right-c1",data: []), DataProvider(name: "right-c2",data: []) ]) data.append(extraDataLeftPane) data[0].data.append(DataProvider(name: "right-a3", data: [])) } } }
修改后选中左栏首个条目点击添加按钮,右栏会立即显示新增的right-a3条目,不需要切换选中项。
内容的提问来源于stack exchange,提问作者Fred Appelman
相关产品推荐
相关产品推荐

