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

如何将CoreML模型输出的MLMultiArray持久化到Core Data?

持久化CoreML生成的MLMultiArray到Core Data的可行方案

方案一:用Core Data Transformable类型(自定义转换器)

Transformable类型完全适用,但直接依赖默认转换器可能存在兼容性问题,建议自定义ValueTransformer来处理MLMultiArray与可存储数据的双向转换:

  1. 实现自定义转换器
class MLMultiArrayTransformer: ValueTransformer {
    override class func transformedValueClass() -> AnyClass {
        return Data.self
    }
    
    override class func allowsReverseTransformation() -> Bool {
        return true
    }
    
    override func transformedValue(_ value: Any?) -> Any? {
        guard let multiArray = value as? MLMultiArray else { return nil }
        guard multiArray.dataType == .float32 else { return nil }
        
        let count = multiArray.count
        let floatPointer = multiArray.dataPointer.bindMemory(to: Float32.self, capacity: count)
        let buffer = UnsafeBufferPointer(start: floatPointer, count: count)
        return Data(buffer: buffer)
    }
    
    override func reverseTransformedValue(_ value: Any?) -> Any? {
        guard let data = value as? Data else { return nil }
        
        let count = data.count / MemoryLayout<Float32>.stride
        guard let multiArray = try? MLMultiArray(shape: [NSNumber(value: count)], dataType: .float32) else {
            return nil
        }
        
        data.copyBytes(to: multiArray.dataPointer.bindMemory(to: Float32.self, capacity: count))
        return multiArray
    }
}
  1. 注册转换器
    在App启动阶段(比如AppDelegate或SceneDelegate的初始化方法)注册转换器:
ValueTransformer.setValueTransformer(MLMultiArrayTransformer(), forName: NSValueTransformerName(rawValue: "MLMultiArrayTransformer"))
  1. 配置Core Data实体
  • 在Core Data模型编辑器中添加属性,类型选择Transformable
  • 在属性的「Transformer」栏填写MLMultiArrayTransformer(与注册名称一致)
  • 可选勾选「Allow External Storage」,适合存储较大的数组
  1. 读写示例
// 存储
let predictions = try model.prediction(from: input)
let record = PredictionRecord(context: viewContext)
record.predictionArray = predictions.yourMultiArrayOutput

// 读取
if let storedArray = record.predictionArray as? MLMultiArray {
    // 使用存储的MLMultiArray
}

方案二:转换为Data后存储到Binary Data字段

如果不想用Transformable,直接将MLMultiArray转为Data,存储到Core Data的Binary Data类型字段,可控性更强:

  1. 配置Core Data实体
    添加一个Binary Data类型的属性,可选勾选「Allow External Storage」;建议额外添加一个Transformable属性存储数组的shape(还原时需要)。

  2. 转换工具方法

// MLMultiArray转Data
func multiArrayToData(_ array: MLMultiArray) -> Data? {
    guard array.dataType == .float32 else { return nil }
    let count = array.count
    let floatPointer = array.dataPointer.bindMemory(to: Float32.self, capacity: count)
    let buffer = UnsafeBufferPointer(start: floatPointer, count: count)
    return Data(buffer: buffer)
}

// Data转MLMultiArray(需要传入原shape)
func dataToMultiArray(_ data: Data, shape: [NSNumber]) -> MLMultiArray? {
    let expectedCount = shape.reduce(1) { $0 * $1.intValue }
    let actualCount = data.count / MemoryLayout<Float32>.stride
    guard expectedCount == actualCount else { return nil }
    
    guard let array = try? MLMultiArray(shape: shape, dataType: .float32) else {
        return nil
    }
    
    data.copyBytes(to: array.dataPointer.bindMemory(to: Float32.self, capacity: actualCount))
    return array
}
  1. 读写示例
// 存储
let predictions = try model.prediction(from: input)
let record = PredictionRecord(context: viewContext)
record.arrayData = multiArrayToData(predictions.yourMultiArrayOutput)
record.arrayShape = predictions.yourMultiArrayOutput.shape

// 读取
if let data = record.arrayData, let shape = record.arrayShape as? [NSNumber], let array = dataToMultiArray(data, shape: shape) {
    // 使用还原后的MLMultiArray
}

方案三:结构化存储(适合简单维度数组)

如果你的MLMultiArray是一维或固定结构的,可转为JSON字符串存储到Core Data的String字段:

// MLMultiArray转JSON字符串
func multiArrayToJSON(_ array: MLMultiArray) -> String? {
    guard array.dataType == .float32 else { return nil }
    let count = array.count
    let floatPointer = array.dataPointer.bindMemory(to: Float32.self, capacity: count)
    let values = Array(UnsafeBufferPointer(start: floatPointer, count: count))
    
    guard let jsonData = try? JSONSerialization.data(withJSONObject: values) else {
        return nil
    }
    return String(data: jsonData, encoding: .utf8)
}

// JSON字符串转MLMultiArray
func jsonToMultiArray(_ jsonString: String) -> MLMultiArray? {
    guard let jsonData = jsonString.data(using: .utf8), let values = try? JSONSerialization.jsonObject(with: jsonData) as? [Float32] else {
        return nil
    }
    
    guard let array = try? MLMultiArray(shape: [NSNumber(value: values.count)], dataType: .float32) else {
        return nil
    }
    
    let floatPointer = array.dataPointer.bindMemory(to: Float32.self, capacity: values.count)
    for (index, value) in values.enumerated() {
        floatPointer[index] = value
    }
    return array
}

读写时直接调用上述方法即可,存储到String类型的Core Data属性中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 16:35:14