我编写了一个自定义 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')
}
}
您可以在 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 }
}