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

Swift Core Data中NSKeyedUnarchiver错误排查与修复请求

错误原因定位
  1. NSKeyedUnarchiver错误根源

    • 核心问题是id字段的类型处理不匹配:要么DTO的id是基本数值类型(如Int),但Core Data实体里id被设为需要归档的类型,要么自定义值转换器返回了非对象类型(比如直接返回Int而非NSNumber),导致NSKeyedUnarchiver解码时无法识别为合法对象,触发警告。
    • 若你给id字段勾选了Core Data的“允许归档”选项,原生数值类型被强制归档也会引发这个问题。
  2. Core Data错误码133000的关联原因

    • 这个错误是因为代码尝试访问的托管对象已无效:可能是id字段存储异常,导致Core Data无法通过唯一约束匹配到正确实体;或是唯一约束冲突后对象被标记为无效,但后续代码仍尝试访问它;也可能是上下文被释放后,对象变成了“僵尸对象”。
修复方案

修正id字段的类型与转换逻辑

  • 优先使用Core Data原生类型:如果DTO的id是Int/UInt等数值类型,直接把Core Data实体PetEntity的id字段类型设为Integer 64,无需自定义值转换器——原生数值类型不需要归档,Core Data会自动处理存储与读取。
  • 若必须用值转换器:确保转换器的两个方法都返回对象类型,示例代码:
    class IDValueTransformer: ValueTransformer {
        override func transformedValue(_ value: Any?) -> Any? {
            guard let id = value as? Int else { return nil }
            return NSNumber(value: id) // 返回NSNumber对象,而非基本类型Int
        }
    
        override func reverseTransformedValue(_ value: Any?) -> Any? {
            guard let number = value as? NSNumber else { return nil }
            return number.intValue
        }
    
        static func register() {
            ValueTransformer.setValueTransformer(IDValueTransformer(), forName: NSValueTransformerName(rawValue: "IDValueTransformer"))
        }
    }
    
  • 移除Core Data实体中id字段的“允许归档”设置(如果之前勾选过)。

解决Core Data 133000错误

  • 规范唯一约束下的CRUD逻辑:先查询再创建/更新,避免冲突导致对象无效,示例代码:
    func savePet(from dto: PetDTO, context: NSManagedObjectContext) throws {
        let fetchRequest: NSFetchRequest<PetEntity> = PetEntity.fetchRequest()
        fetchRequest.predicate = NSPredicate(format: "id == %@", NSNumber(value: dto.id))
        
        if let existingPet = try context.fetch(fetchRequest).first {
            // 更新现有对象
            existingPet.name = dto.name
            // 其他字段赋值
        } else {
            // 创建新对象
            let newPet = PetEntity(context: context)
            newPet.id = dto.id
            newPet.name = dto.name
            // 其他字段赋值
        }
        try context.save()
    }
    
  • 处理保存冲突:添加冲突捕获逻辑,避免对象因合并冲突被标记为无效:
    do {
        try context.save()
    } catch let error as NSError where error.code == NSManagedObjectMergeConflictError {
        context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
        try context.save()
    } catch {
        print("Core Data保存失败:\(error)")
    }
    
  • 管理上下文生命周期:确保访问托管对象时,对应的NSManagedObjectContext处于活跃状态,避免上下文被释放后对象失效。

验证与调试

  • 使用Core Data Debugger查看存储中id字段的实际值,确认类型和数值正确。
  • 开启SQL调试,查看Core Data生成的SQL语句,验证id字段的查询、插入逻辑:
    // 在AppDelegate的didFinishLaunchingWithOptions中添加
    UserDefaults.standard.set(true, forKey: "NSDebugEnabled")
    UserDefaults.standard.set(true, forKey: "NSShowSQLLogging")
    

内容的提问来源于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 10:18:18