You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI:如何触发列表行更新?修改结构体字段时列表不刷新

SwiftUI列表不刷新的问题解析与解决

问题根源

你的Fragment和Source是值类型(结构体),而@Published修饰的数组只会在容器本身发生变更时发布更新通知——比如插入/删除元素、或者替换整个元素实例。当你修改结构体内部的某个字段时:

  1. 数组本身没有被重新赋值,@Published不会触发通知;
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 05:10:37