SwiftUI:如何触发列表行更新?修改结构体字段时列表不刷新
SwiftUI列表不刷新的问题解析与解决
问题根源
你的Fragment和Source是值类型(结构体),而@Published修饰的数组只会在容器本身发生变更时发布更新通知——比如插入/删除元素、或者替换整个元素实例。当你修改结构体内部的某个字段时:
- 数组本身没有被重新赋值,
@Published不会触发通知; ForEach通过id识别列表项,因为id未变化,SwiftUI会判定该行数据没有变更,不会重新渲染对应行。
解决方案
方案一:将结构体转为ObservableObject类
把Fragment和Source改成遵循ObservableObject的类,用@Published标记需要监测的内部属性:
class Fragment: ObservableObject, Identifiable, Hashable { let id: UUID @Published var content: String // 示例字段,根据你的实际需求替换 init(id: UUID, content: String) { self.id = id self.content = content } // 实现Hashable协议 static func == (lhs: Fragment, rhs: Fragment) -> Bool { lhs.id == rhs.id } func hash(into hasher: inout Hasher) { hasher.combine(id) } } // Source类同理改造
然后在子视图中用ObservedObject绑定实例,监测内部属性变化:
struct FragmentView: View { @ObservedObject var fragment: Fragment var body: some View { Text(fragment.content) } }
这样修改fragment.content时,@Published会自动发布通知,对应的列表行会实时刷新。
方案二:保持结构体,修改时替换数组元素
如果想继续使用结构体,修改字段时需要创建新的结构体实例,替换数组中的对应元素,触发@Published的数组更新:
// 示例:修改指定id的Fragment的content字段 func updateFragmentContent(id: UUID, newContent: String) { guard let index = projectModel.fragments.firstIndex(where: { $0.id == id }) else { return } var updatedFragment = projectModel.fragments[index] updatedFragment.content = newContent projectModel.fragments[index] = updatedFragment }
替换元素后,数组本身发生了变更,@Published会发布通知,列表会刷新对应行。
内容的提问来源于stack exchange,提问作者Altair Jones
相关产品推荐
相关产品推荐

