SwiftData ValueTransformer 存储 `.transformable(by:` 对象的集合?

问题描述 投票:0回答:1

我编写了一个自定义 ValueTransformer 来存储未接收 SwiftData 自动合规性的对象类型:

我现在想在 SwiftData 模型上存储与变量相同类型的集合:

@Model
class TestModel {
    // Works after adding custom MeasurementTransformer
    @Attribute(.transformable(by: MeasurementTransformer.self)) let measurement: NSMeasurement

    // Not working
    let measurementArray: [NSMeasurement]
    let measurementDict: [String: NSMeasurement]
    
    init(measurement: NSMeasurement, measurementArray: [NSMeasurement], measurementDict: [String : NSMeasurement]) {
        self.measurement = measurement
        self.measurementArray = measurementArray
        self.measurementDict = measurementDict
    }
}

这会引发数组和字典错误:

在“Array”上引用实例方法“setValue(forKey:to:)”要求“NSMeasurement”符合“PersistentModel”
在“Array”上引用实例方法“getValue(forKey:)”要求“NSMeasurement”符合“PersistentModel”

当该类型打包到数组或字典中时,

@Attribute(.transformable(by:
(或任何其他方式)是否有任何特殊语法可以在单对象转换器和转换器之间共享代码?或者我是否需要为该类型出现在集合中的每种情况编写全新的 ValueTransformers?


然后,当我实际尝试为集合添加 ValueTransformer 时,集合实现

NSCoding
或转换为
AnyClass
似乎存在问题。大概是因为 Swift 集合是
struct
而不是
class
?对于集合来说,有 ValueTransformer 的替代品吗?

final class MeasurementArrayTransformer: ValueTransformer {
    static let name = NSValueTransformerName(rawValue: "MeasurementArrayTransformer")

    override func transformedValue(_ value: Any?) -> Any? {
        guard let measurements = value as? [NSMeasurement] else { return nil }
        do { return try NSKeyedArchiver.archivedData(withRootObject: measurements, requiringSecureCoding: true) } catch { debugPrint(error); return nil }
    }
    
    override func reverseTransformedValue(_ value: Any?) -> Any? {
        guard let data = value as? Data else { return nil }
        do { return try NSKeyedUnarchiver.unarchivedObject(ofClass: [NSMeasurement].self, from: data) } catch { debugPrint(error); return nil }
        // ERROR: Static method 'unarchivedObject(ofClass:from:)' requires that '[NSMeasurement]' conform to 'NSCoding'
    }
    
    override class func allowsReverseTransformation() -> Bool { true }
    
    override class func transformedValueClass() -> AnyClass {
        [NSMeasurement].self
        // ERROR: Cannot convert return expression of type '[NSMeasurement].Type' to return type 'AnyClass' (aka 'any AnyObject.Type')
    }
}
core-data swift-data nsvaluetransformer
1个回答
0
投票

您可以在 Model 类中将属性的类型保留为 Swift Array,然后在将其存储在 SwiftData / Core Data 中时桥接到 ValueTransformer 中的 NSArray:

@Attribute(.transformable(by: MeasurementArrayTransformer.self)) let measurementArray: [NSMeasurement]

使用

NSArray.self
作为 ValueTransformer 的
transformedValueClass
并转换为 NSArray 或从 NSArray 转换:

final class MeasurementArrayTransformer: ValueTransformer {
    static let name = NSValueTransformerName(rawValue: "MeasurementArrayTransformer")

    override func transformedValue(_ value: Any?) -> Any? {
        guard let measurements = value as? [NSMeasurement] else { return nil }
        let nsArray = measurements as NSArray
        do {
            return try NSKeyedArchiver.archivedData(withRootObject: nsArray, requiringSecureCoding: true)
        } catch {
            debugPrint(error);
            return nil
        }
    }
    
    override func reverseTransformedValue(_ value: Any?) -> Any? {
        guard let data = value as? Data else { return nil }
        do {
            let nsArray = try NSKeyedUnarchiver.unarchivedObject(ofClass: NSArray.self, from: data)
            guard let measurements = nsArray as? [NSMeasurement] else { return nil }
            return measurements
        } catch {
            debugPrint(error);
            return nil
        }
    }
    
    override class func allowsReverseTransformation() -> Bool { true }
    override class func transformedValueClass() -> AnyClass { NSArray.self }
}
© www.soinside.com 2019 - 2024. All rights reserved.