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

SwiftData修改项目名称无法持久化问题求助

问题分析与修复方案

核心问题

你的代码中,所有修改操作(名称、数量、完成状态)都仅修改了本地@State变量的副本,没有同步到SwiftData的Einkauf模型对象,因此这些更改无法被持久化保存。新增功能正常是因为你直接通过ModelContext插入了新的模型对象。

具体修复步骤

1. 重构EinkaufItemRowView,直接绑定模型对象

不要单独传递name、anzahl等属性,直接传入Einkauf模型实例,用@Bindable包装(SwiftData的@Model类默认遵循Observable协议,@Bindable可实现视图与模型属性的双向绑定)。

修改后的EinkaufItemRowView:

struct EinkaufItemRowView: View {
    @Bindable var item: Einkauf
    @State private var isDone: Bool
    
    init(item: Einkauf) {
        self.item = item
        // 初始化时同步模型的完成状态到本地State
        self._isDone = State(initialValue: item.isDone ?? false)
    }
    
    var body: some View {
        HStack {
            Image(systemName: isDone ? "checkmark.circle.fill" : "checkmark.circle")
                .resizable()
                .frame(width: 30, height: 30)
                .foregroundStyle(isDone ? .green : .primary)
                .padding(.horizontal)
                .onTapGesture {
                    isDone.toggle()
                    item.isDone = isDone // 将状态同步到模型
                }
            
            // 直接绑定模型的name属性,修改时自动同步
            TextField(item.name, text: $item.name)
                .strikethrough(isDone)
                .font(.title2)
            
            Spacer()
            
            Button(action: {
                guard item.anzahl > 0 else { return }
                item.anzahl -= 1 // 直接修改模型的数量属性
            }, label: {
                Image(systemName: "minus.circle")
                    .resizable()
                    .foregroundStyle(.red)
                    .frame(width: 30, height: 30)
            })
            
            Button(action: {
                item.anzahl += 1 // 直接修改模型的数量属性
            }, label: {
                Image(systemName: "plus.circle")
                    .resizable()
                    .foregroundStyle(.green)
                    .frame(width: 30, height: 30)
            })
            
            // 直接显示模型中的数量值
            Text("\(item.anzahl)")
                .frame(width: 40)
                .padding(.horizontal, 5)
                .font(.title2)
                .bold()
        }
    }
}

2. 调整EinkaufslisteDetailView的列表渲染逻辑

在ForEach中直接传递Einkauf实例给行视图,移除无用的本地状态变量:

struct EinkaufslisteDetailView: View {
    @Environment (\.modelContext) var context
    @ObservedObject var vm: EinkaufViewModel
    @Query var items2: [Einkauf]
    let kategorieName: String
    
    var body: some View {
        NavigationStack {
            List {
                ForEach(items2) { item in
                    EinkaufItemRowView(item: item)
                        .padding(.vertical)
                }
                .onDelete { indexSet in
                    for index in indexSet {
                        context.delete(items2[index])
                    }
                }
            }
            .listStyle(.plain)
            .navigationBarItems(
                trailing: Button(action: { vm.addItem(context: context) },
                                label: {
                    Image(systemName: "plus.circle")
                        .resizable()
                        .frame(width: 30, height: 30)
                })
            )
            .navigationTitle(kategorieName)
        }
    }
}

3. 确保Einkauf模型定义完整

你的Einkauf模型需要包含对应属性,示例如下:

@Model
class Einkauf {
    var name: String
    var anzahl: Int
    var isDone: Bool? // 根据需求设置为可选或非可选
    
    init(name: String, anzahl: Int, isDone: Bool? = false) {
        self.name = name
        self.anzahl = anzahl
        self.isDone = isDone
    }
}

关键原理

SwiftData的持久化依赖于修改@Model标记的对象属性,ModelContext会自动跟踪这些更改并完成保存。如果仅修改本地@State变量的副本,这些更改不会同步到模型对象,自然无法被持久化。使用@Bindable可以让视图直接绑定模型属性,修改操作会自动同步到模型,由SwiftData负责持久化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 01:40:54