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

SwiftData中CourseSchemeModel的holes字段无法持久化更新求助

问题分析与解决方案

你遇到的问题核心在于SwiftData对结构体数组属性的追踪与持久化逻辑,修改name生效但holes不生效,大概率是结构体的序列化或SwiftData的变更检测机制导致的,以下是具体解决步骤:

1. 修正HoleModel的可变ID问题

你的HoleModel中id是可变的var类型,每次结构体实例化或修改时都会生成新UUID,这会干扰SwiftData的序列化与变更检测。将其改为不可变的let:

struct HoleModel : Identifiable, Codable, Hashable {
    let id = UUID() // 改为let,固定UUID
    var holeNumber : Int
    var par : Int
    var holeDistance : Int
    
    init(holeNumber: Int, par: Int, holeDistance: Int) {
        self.holeNumber = holeNumber
        self.par = par
        self.holeDistance = holeDistance
    }
}

2. 显式标记holes属性为可转换类型

SwiftData默认支持Codable结构体,但对数组类型的结构体属性,显式指定转换规则能避免序列化模糊问题。给CourseSchemeModel的holes添加@Attribute(.transformable)标记,并自定义JSON转换器:

先添加自定义转换器

struct JSONTransformer<T: Codable>: ValueTransformer {
    override class func transformedValueClass() -> AnyClass {
        return Data.self
    }
    
    override class func allowsReverseTransformation() -> Bool {
        return true
    }
    
    override func transformedValue(_ value: Any?) -> Any? {
        guard let items = value as? T else { return nil }
        return try? JSONEncoder().encode(items)
    }
    
    override func reverseTransformedValue(_ value: Any?) -> Any? {
        guard let data = value as? Data else { return nil }
        return try? JSONDecoder().decode(T.self, from: data)
    }
}

修改CourseSchemeModel

@Model
final class CourseSchemeModel {
    /* TODO: curate who created the model */
    
    @Attribute(.unique)
    var id: Int
    var name: String
    var longitude: Double
    var latitude: Double
    var url: String
    // 显式指定转换器
    @Attribute(.transformable(by: JSONTransformer<[HoleModel]>.self))
    var holes: [HoleModel]
    
    init(id: Int, name: String, longitude: Double, latitude: Double, url: String) {
        self.id = id
        self.name = name
        self.longitude = longitude
        self.latitude = latitude
        self.url = url
        holes = []
    }
}

3. 规范模型修改逻辑

你的updateHoles方法中获取course的方式有问题(courses.where返回数组而非单个实例),且未显式利用ModelContext进行事务处理,这可能导致变更未被正确提交:

struct DemoView {
    @Query var courses: [CourseSchemeModel]
    // 注入ModelContext
    @Environment(\.modelContext) private var modelContext

    var body: some View {
        ...
    }
    
    func updateHoles(id: Int, holes: [HoleModel]) {
        // 获取单个课程实例
        guard let course = courses.first(where: { $0.id == id }) else { return }
        
        do {
            // 在事务中修改,确保原子性
            modelContext.transaction {
                course.holes = holes
            }
            // 手动触发保存,避免自动保存延迟
            try modelContext.save()
        } catch {
            print("保存球洞数据失败: \(error.localizedDescription)")
        }
    }
}

额外检查项

  • 重置模拟器或删除APP重新安装,避免旧的数据库结构干扰
  • 确认传入的holes数组数据格式正确,无空值或非法数据
  • 可以通过Xcode的调试面板查看course实例的holes属性是否已被修改

内容的提问来源于stack exchange,提问作者one friendly programmer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 01:58:11