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

Core Data数据保存异常排查:上下文使用与编码问题咨询

问题分析与解决方案

1. 上下文操作的根本性错误

你最初的代码存在两个核心问题:

  • 创建的managedObjectContext完全独立于App的持久化容器,属于孤立上下文,即便保存也不会将数据写入持久化存储;
  • 错误调用self.context.save()而非新创建的上下文,导致所有操作无持久化效果。

后续改存managedObjectContext仍失效,是因为该上下文未绑定持久化容器的存储协调器,也未设置父上下文,数据仅存在于该上下文的内存中,主上下文无法感知。

正确的上下文使用方式

方式一:直接使用主上下文(适合主线程简单操作)

移除多余的上下文创建,直接基于主上下文操作:

let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

func add(pet: PetDTO) {
    context.perform {
        let newPet = PetEntity(context: self.context)
        
        newPet.id = Int64(pet.id)
        newPet.name = pet.name
        newPet.category = pet.category
        newPet.photoUrls = pet.photoUrls
        newPet.tags = pet.tags
        newPet.status = pet.status.rawValue
        
        do {
            try self.context.save()
        } catch {
            print("保存失败:\(error)")
        }
    }
}

方式二:使用私有上下文(适合后台操作,避免阻塞主线程)

基于持久化容器创建私有上下文,关联主上下文作为父上下文,保存后自动同步:

let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

func add(pet: PetDTO) {
    let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
    privateContext.parent = self.context // 关联主上下文
    
    privateContext.perform {
        let newPet = PetEntity(context: privateContext)
        
        newPet.id = Int64(pet.id)
        newPet.name = pet.name
        newPet.category = pet.category
        newPet.photoUrls = pet.photoUrls
        newPet.tags = pet.tags
        newPet.status = pet.status.rawValue
        
        do {
            try privateContext.save() // 先保存私有上下文
            self.context.perform { // 同步到主上下文
                do {
                    try self.context.save()
                } catch {
                    print("主上下文同步失败:\(error)")
                }
            }
        } catch {
            print("私有上下文保存失败:\(error)")
        }
    }
}

2. 134060错误的根源:值转换器重构问题

Error Domain=NSCocoaErrorDomain Code=134060错误来自值转换器的异常,和你的重构操作直接相关:

  • 检查拆分后的自定义值转换器是否正确注册到Core Data模型:在模型编辑器中,对应字段的「Value Transformer」需设置正确的转换器名称,必要时勾选「Allow External Storage」;
  • 确认值转换器实现了安全编码:如果使用NSSecureUnarchiveFromData,你的DTO类(如CategoryDTO)必须正确实现NSSecureCoding协议,而非旧的NSCoding;
  • 验证值转换器的方法逻辑:transformedValue(_:)和reverseTransformedValue(_:)需正确处理输入输出,避免编码时崩溃。

3. nil字段的验证方向

你怀疑category为nil导致错误,可从两点验证:

  • 打开Core Data模型文件,检查PetEntity的category字段是否勾选「Optional」(允许为空),未勾选时传入nil会触发保存失败;
  • 检查值转换器是否能处理nil值:在transformedValue(_:)方法中,输入为nil时需返回nil或合法默认值,避免编码异常。

4. 上下文同步的解决思路

“主上下文无法获取另一个上下文的保存数据”,本质是上下文未关联。只要按照上述两种正确方式使用上下文,要么直接用主上下文操作,要么给私有上下文设置主上下文为父上下文,保存后数据会自动同步,主上下文就能读取到新数据。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 14:54:24