首页 > 解决方案 > 通用快速对象序列化?

问题描述

是否有通用的方法来序列化/反序列化 iOS 对象?我正在使用以下代码,并且我调用的系统函数在 iOS 12 中已弃用:

  func object(forKey:String) -> Any? {
    if let data = get(BLOB_COL, forKey) {
      return NSKeyedUnarchiver.unarchiveObject(with: data as! Data)
    }
    return nil
  }

  func set(_ object:Any, forKey: String) {
    let data = NSKeyedArchiver.archivedData(withRootObject: object)
    updateOrInsert(forKey, BLOB_COL, data)
  }

看起来这些函数的新版本需要对象类的知识,以及用于取消归档不同集合类型的不同签名......有没有一种简单的方法来处理这个问题?

标签: swiftserializationdeserialization

解决方案


如果你想使用 NSKeyedArchiver/NSKeyedUnarchiver:

归档更改时:

NSKeyedArchiver.archivedData...

NSKeyedArchiver.archivedData(withRootObject: object, requiringSecureCoding: false)

当取消归档更改时

NSKeyedUnarchiver.unarchiveObject...

NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data)

可编码协议通用方法

如果您想使用 Codable 进行编码和解码(序列化),您Data可以扩展 Encodable 协议并创建一个方法来编码符合它的任何对象:

extension Encodable {
    func data(using encoder: JSONEncoder = JSONEncoder()) throws -> Data { try encoder.encode(self) }
}

要解码编码数据,您可以扩展Data并创建一个通用方法来解码任何符合 Decodable 的对象:

extension Data {
    func object<T: Decodable>(using decoder: JSONDecoder = JSONDecoder()) throws -> T {
        try decoder.decode(T.self, from: self)
    }
    // you can also create a string property to convert the JSON data to String
    var string: String? { String(data: self, encoding: .utf8) }
}

用法:

struct Person: Codable {
    let name: String
    let age: Int
}

do {
    // encoding
    let person = Person(name: "Joe", age: 10)
    var people = [Person]()
    people.append(person)
    let data = try people.data()
    print(data.string ?? "")  // [{"name":"Joe","age":10}]
    // decoding
    let loadedPeople: [Person] = try data.object()
    loadedPeople.forEach({print( $0.name, $0.age)})  // Joe 10
} catch {
    print(error)
}

推荐阅读