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

如何为[[Int?]]与[[String?]]实现Core Data Transformable类型支持

报错原因

你遇到的报错本质是:NSKeyedUnarchiver的unarchivedObject(ofClass:from:)方法要求解析的类型必须遵守NSCoding协议,而Swift原生的二维可选数组([[Int32?]]、[[String?]])、自定义TileModel结构体都默认不遵守NSCoding,所以无法直接用基于NSCoding的转换器实现序列化。

解决方案

因为你所有需要持久化的类型都已经遵守Codable协议,完全可以抛弃NSCoding那套逻辑,直接基于JSONEncoder/JSONDecoder实现自定义转换器,步骤如下:

  1. 实现通用泛型Codable转换器
    不用单独写三个重复的转换器,直接写一个通用的泛型类复用逻辑:
class CodableValueTransformer<T: Codable>: ValueTransformer {
    override class func transformedValueClass() -> AnyClass {
        return NSData.self
    }
    
    override class func allowsReverseTransformation() -> Bool {
        return true
    }
    
    override func transformedValue(_ value: Any?) -> Any? {
        guard let value = value as? T else { return nil }
        do {
            return try JSONEncoder().encode(value)
        } catch {
            print("序列化失败: \(error)")
            return nil
        }
    }
    
    override func reverseTransformedValue(_ value: Any?) -> Any? {
        guard let data = value as? Data else { return nil }
        do {
            return try JSONDecoder().decode(T.self, from: data)
        } catch {
            print("反序列化失败: \(error)")
            return nil
        }
    }
}

// 扩展Transformer名称,方便注册调用
extension NSValueTransformerName {
    static let lettersTransformer = NSValueTransformerName(rawValue: "LettersTransformer")
    static let valuesTransformer = NSValueTransformerName(rawValue: "ValuesTransformer")
    static let tilesTransformer = NSValueTransformerName(rawValue: "TilesTransformer")
}
  1. 注册对应类型的转换器
    在Persistence.swift的初始化方法中,注册三个对应类型的转换器实例:
init(inMemory: Bool = false) {
    // 注册三个对应类型的转换器
    ValueTransformer.setValueTransformer(
        CodableValueTransformer<[[String?]]>(), 
        forName: .lettersTransformer
    )
    ValueTransformer.setValueTransformer(
        CodableValueTransformer<[[Int32?]]>(), 
        forName: .valuesTransformer
    )
    ValueTransformer.setValueTransformer(
        CodableValueTransformer<[TileModel]?>(), 
        forName: .tilesTransformer
    )

    container = NSPersistentContainer(name: "TransApp")
    // 原有持久化容器初始化逻辑保持不变
}
  1. 配置Core Data实体属性
    打开你的.xcdatamodeld数据模型文件,对三个属性做如下配置:
  • 类型选择Transformable
  • Transformer栏填写你注册的转换器名称,比如letters属性就填LettersTransformer
  • Custom Class栏填写对应Swift类型,比如letters属性就填[[String?]]

配置完成后清理项目重新编译即可解决报错。

可选替代方案

如果你不想用Transformable类型,也可以直接把三个属性在Core Data中设置为Binary Data类型,在toEntity方法和实体转模型的方法中自己实现序列化/反序列化逻辑,效果和自定义转换器完全一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 15:36:07