问题描述
我希望使用 Core Data 存储 MKpolyline 属性,但我能找到的唯一答案是旧的,并且使用 iOS 12 中已弃用的存档函数 (NSKeyedUnarchiver.unarchiveObjectWithData)。它们已被那些需要类的 (NSKeyedUnarchiver.unarchivedobject) 替换,并且不允许使用 MKpolyline,因为它不符合 NSCoding。 Here is the no longer supported version:
我已在 xcdatamodeld 中将该属性设置为 Transformable,并尝试创建 Transformer 函数以允许自动值转换。但是我收到错误“静态方法‘unarchivedobject(ofClass:from:)’要求‘MKpolyline’符合‘NSCoding’”。
我已经尝试了几种方法来让 MKpolyline 支持 Codable,但我似乎也无法做到这一点。
这是我的值转换器代码:
import Foundation
import MapKit
@objc(MKpolylineValueTransformer)
public final class MKpolylineValueTransformer: ValueTransformer {
override public class func transformedValueClass() -> AnyClass {
return MKpolyline.self
}
override public class func allowsReverseTransformation() -> Bool {
return true
}
override public func transformedValue(_ value: Any?) -> Any? {
guard let polyline = value as? MKpolyline else { return nil }
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: polyline,requiringSecureCoding: true)
return data
} catch {
assertionFailure("Failed to transform `MKpolyline` to `Data`")
return nil
}
}
override public func reverseTransformedValue(_ value: Any?) -> Any? {
guard let data = value as? NSData else { return nil }
do {
let polyline = NSKeyedUnarchiver.unarchivedobject(ofClass: MKpolyline,from: data as Data)
return polyline
} catch {
assertionFailure("Failed to transform `Data` to `MKpolyline`")
return nil
}
}
}
extension MKpolylineValueTransformer {
/// Register the transformer.
static let name = NSValueTransformerName(rawValue: String(describing: MKpolylineValueTransformer.self))
public static func register() {
let transformer = MKpolylineValueTransformer()
ValueTransformer.setValueTransformer(transformer,forName: name)
}
}
作为另一种方法,我在折线中获取点并构建了一个自定义类来存储数据。这主要是因为我可以成功存储对象,但 NSUnarchive 返回 nil 导致“致命错误:在解包可选值时意外发现 nil”。
代码如下:
import Foundation
import MapKit
public extension MKMultiPoint {
var coordinates: [CLLocationCoordinate2D] {
var coords = [CLLocationCoordinate2D](repeating: kCLLocationCoordinate2DInvalid,count: pointCount)
getCoordinates(&coords,range: NSRange(location: 0,length: pointCount))
return coords
}
}
class CodableCoordinate: NSObject,NSSecureCoding {
static var supportsSecureCoding: Bool = true
var latitude: Double = 0
var longitude: Double = 0
init(latitude: Double,longitude: Double) {
self.latitude = latitude
self.longitude = longitude
}
required init(coder aDecoder: NSCoder) {
super.init()
latitude = aDecoder.decodeDouble(forKey: "latitude")
longitude = aDecoder.decodeDouble(forKey: "longitude")
}
func encode(with coder: NSCoder) {
coder.encode(latitude,forKey: "latitude")
coder.encode(longitude,forKey: "longitude")
}
}
class CodableCoordinatesArray: NSObject,NSSecureCoding {
static var supportsSecureCoding: Bool = true
var coordinatesArray: [CodableCoordinate]
init(coordinatesArray: [CodableCoordinate]) {
self.coordinatesArray = coordinatesArray
}
required init(coder aDecoder: NSCoder) {
let x = aDecoder.decodeObject(forKey:"coordinatesArray")
coordinatesArray = aDecoder.decodeObject(forKey: "coordinatesArray") as! [CodableCoordinate]
}
convenience init(fromMKpolyline polyline: MKpolyline) {
self.init(coordinatesArray: [CodableCoordinate]())
for coord in polyline.coordinates {
coordinatesArray.append(CodableCoordinate(latitude: coord.latitude,longitude: coord.longitude))
}
}
func encode(with coder: NSCoder) {
coder.encode(coordinatesArray,forKey:"coordinatesArray")
}
func polyline() -> MKpolyline? {
if coordinatesArray.isEmpty { return nil }
var coords = [CLLocationCoordinate2D]()
for coord in coordinatesArray {
coords.append(CLLocationCoordinate2D(latitude: coord.latitude,longitude: coord.longitude))
}
return MKpolyline(coordinates: coords,count: coords.count)
}
}
@objc(MKpolylineValueTransformer)
public final class MKpolylineValueTransformer: ValueTransformer {
override public class func transformedValueClass() -> AnyClass {
return MKpolyline.self
}
override public class func allowsReverseTransformation() -> Bool {
return true
}
override public func transformedValue(_ value: Any?) -> Any? {
guard let polyline = value as? MKpolyline else { return nil }
do {
let arrayFrompolyline = CodableCoordinatesArray(fromMKpolyline: polyline)
let data = try NSKeyedArchiver.archivedData(withRootObject: arrayFrompolyline,requiringSecureCoding: true)
return data
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError),\(nsError.userInfo)")
}
}
override public func reverseTransformedValue(_ value: Any?) -> Any? {
guard let data = value as? NSData else { return nil }
do {
let coordinatesArray = try NSKeyedUnarchiver.unarchivedobject(ofClass: CodableCoordinatesArray.self,from: data as Data)
return coordinatesArray?.polyline()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError),\(nsError.userInfo)")
}
}
}
extension MKpolylineValueTransformer {
static let name = NSValueTransformerName(rawValue: String(describing: MKpolylineValueTransformer.self))
/// Registers the value transformer
public static func register() {
let transformer = MKpolylineValueTransformer()
ValueTransformer.setValueTransformer(transformer,forName: name)
}
}
仅供参考,包含以下行是为了让我在投射前检查解码:
let x = aDecoder.decodeObject(forKey:"coordinatesArray")
谢谢
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)