Core Data转换器报错:无法将[[[CLLocationCoordinate2D.Type]]]转为AnyClass
Core Data可转换属性处理
[[[CLLocationCoordinate2D]]]的解决方案 错误原因
allowedTopLevelClasses写法错误:该属性要求返回类类型数组([AnyClass]),你写的[[[[CLLocationCoordinate2D.self]]]]是嵌套数组类型,和要求的元素类型AnyClass完全不匹配。- 类型本质不兼容:
CLLocationCoordinate2D是结构体(值类型),CLLocationCoordinate2D.self属于结构体类型,不属于AnyClass(AnyClass等价于AnyObject.Type,仅类类型符合要求)。教程中UIColor.self能生效,是因为UIColor是继承自NSObject的类。
解决方案
由于CLLocationCoordinate2D不是类,无法直接作为Core Data可转换属性的类型,可通过以下两种方式处理:
方案一:用NSValue包装坐标结构体
将CLLocationCoordinate2D包装为NSValue(类类型),再处理嵌套数组的转换:
import CoreData import CoreLocation class CoordinateArrayTransformer: ValueTransformer { // 声明转换后的数据类型为NSArray override static func transformedValueClass() -> AnyClass { NSArray.self } // 支持反向转换(从Core Data读取转成原类型) override static var allowsReverseTransformation: Bool { true } // 将[[[CLLocationCoordinate2D]]]转成Core Data可存储的[[[NSValue]]] override func transformedValue(_ value: Any?) -> Any? { guard let coordinates = value as? [[[CLLocationCoordinate2D]]] else { return nil } return coordinates.map { outerArr in outerArr.map { middleArr in middleArr.map(NSValue.init(mkCoordinate:)) } } as NSArray } // 将Core Data存储的[[[NSValue]]]转回[[[CLLocationCoordinate2D]]] override func reverseTransformedValue(_ value: Any?) -> Any? { guard let nsValues = value as? [[[NSValue]]] else { return nil } return nsValues.map { outerArr in outerArr.map { middleArr in middleArr.compactMap { nsVal in nsVal.objCType == MKCoordinateObjCType ? nsVal.mkCoordinateValue : nil } } } } // 声明允许的顶层类:NSArray(嵌套数组的顶层容器)和NSValue(存储坐标的类) override static var allowedTopLevelClasses: [AnyClass] { [NSArray.self, NSValue.self] } } // 注册转换器 extension CoordinateArrayTransformer { static let name = NSValueTransformerName(rawValue: "CoordinateArrayTransformer") static func register() { ValueTransformer.setValueTransformer(Self(), forName: name) } }
使用步骤:
- App启动时调用
CoordinateArrayTransformer.register()注册转换器 - 在Core Data模型编辑器中,将目标属性的类型设为
Transformable,并在Transformer下拉菜单中选择CoordinateArrayTransformer
方案二:通过Codable转Data存储
利用CLLocationCoordinate2D本身符合Codable的特性,将嵌套数组编码为Data存储:
import CoreData import CoreLocation class CoordinateArrayTransformer: ValueTransformer { override static func transformedValueClass() -> AnyClass { Data.self } override static var allowsReverseTransformation: Bool { true } // 将坐标数组编码为Data override func transformedValue(_ value: Any?) -> Any? { guard let coordinates = value as? [[[CLLocationCoordinate2D]]] else { return nil } return try? JSONEncoder().encode(coordinates) } // 将Data解码回坐标数组 override func reverseTransformedValue(_ value: Any?) -> Any? { guard let data = value as? Data else { return nil } return try? JSONDecoder().decode([[[CLLocationCoordinate2D]]].self, from: data) } // 仅需允许Data类作为顶层类型 override static var allowedTopLevelClasses: [AnyClass] { [Data.self] } } // 注册转换器 extension CoordinateArrayTransformer { static let name = NSValueTransformerName(rawValue: "CoordinateArrayTransformer") static func register() { ValueTransformer.setValueTransformer(Self(), forName: name) } }
使用步骤和方案一一致。
内容的提问来源于stack exchange,提问作者whaleshark
相关产品推荐
相关产品推荐

