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

如何在SwiftUI中更新ObservableObject内数组的指定元素属性

你的代码不生效的核心原因有两个:

  1. Swift中的结构体是值类型,你在updateCompletionCount方法中取出的tempActivity是ViewModel数组中对应元素的拷贝,修改这个拷贝完全不会影响原数组的数据。
  2. 详情页的@State var activity是本地私有状态,和ViewModel里存储的数组元素没有关联,修改本地值不会同步到上层。

以下是两种可行的修改方案:


方案1:MVVM规范写法(推荐,后续易维护)

步骤1:给ViewModel封装更新逻辑

把数据操作逻辑收拢到ViewModel中,避免在View层直接操作数组:

// view model
class ActivityViewModel: ObservableObject {
    @Published var activities: [Activity] = []
    
    // 新增更新完成次数的方法
    func incrementCompletion(for activityId: UUID) {
        guard let index = activities.firstIndex(where: { $0.id == activityId }) else { return }
        activities[index].completions += 1
    }
}

步骤2:修改详情页逻辑

删除本地多余的Activity状态副本,直接调用ViewModel方法更新数据:

// detail view
struct ActivityDetailView: View {
    let activity: Activity
    @ObservedObject var viewModel: ActivityViewModel
    
    var body: some View {
        VStack {
            Text("Number of times completed: \(viewModel.activities.first(where: { $0.id == activity.id })?.completions ?? 0)")
            Button("Increment completion count"){
                viewModel.incrementCompletion(for: activity.id)
            }
            Text("\(activity.completeDescription)")
        }
    }
}

方案2:Binding简化写法(代码更简洁)

直接通过双向绑定关联ViewModel数组元素,无需额外封装方法:

步骤1:修改列表页传值

给ForEach加上$符号获取元素绑定:

List {
    ForEach($viewModel.activities) { $activity in
        NavigationLink(destination: ActivityDetailView(activity: $activity)) {
            HStack {
                VStack {
                    Text(activity.name)
                    Text(activity.miniDescription)
                }
                Text("\(activity.completions)")
            }
        }
    }
}

步骤2:详情页用Binding接收参数

// detail view
struct ActivityDetailView: View {
    @Binding var activity: Activity
    
    var body: some View {
        VStack {
            Text("Number of times completed: \(activity.completions)")
            Button("Increment completion count"){
                activity.completions += 1
            }
            Text("\(activity.completeDescription)")
        }
    }
}

补充小问题修复

你原代码中用到的activity.miniDescription在Model中没有定义,可以给Activity补充计算属性避免报错:

struct Activity: Identifiable {
    var id = UUID()
    var name: String
    var completeDescription: String
    var completions: Int = 0
    
    // 补充缩略描述,可根据业务需求调整规则
    var miniDescription: String {
        String(completeDescription.prefix(10)) + "..."
    }
}

内容的提问来源于stack exchange,提问作者pakobongbong

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 06:15:01