In general, Objective-C files data via NSCoding, while Swift files data in Codable. But that doesn’t mean they can’t work together. It takes a little bit of work to file NSCoding data in Codable. How to understand?

For example, UIColor and UIImage implement NSCoding but not Codable.

Here we use a simple struct example:

struct Person {
    var name: String 
    var favoriteColor: UIColor 
}
Copy the code

How do I make a Person Codable and archive it through JSONEncoder?

We will follow these four steps:

  1. createPersionextensionAnd abide by theCodableagreement
  2. Create a customCodingKeyIs used to describe what data will be saved
  3. implementationinit(from:)Method to convert the raw data toUIColortype
  4. implementationencode(to:)Methods,UIColorData to raw data, like thisCodableYou can encode it base-64

First add extension to Persion:

extension Persion: Codable {}Copy the code

After it is added, compilation fails because UIColor does not implement Codable. Let’s move on to the second step: add custom coding keys.

enum CodingKeys: String.CodingKey {
    case name 
    case favoriteColor
}
Copy the code

We need to manually encode and decode by declaring these coding keys.

Implement decoding operation:

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    name = try container.decode(String.self, forKey: .name)
    // Get the original data
    let colorData = try container.decode(Data.self, forKey: .favoriteColor)
    // Decode
    favoriteColor = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(colorData) as? UIColor ?? UIColor.black
}
Copy the code

Implement coding operations:

func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    try container.encode(name, forKey: .name)
    // Convert to raw data
    let colorData = try NSKeyedArchiver.archivedData(withRootObject: favoriteColor, requiringSecureCoding: false)
    // Encode
    try container.encode(colorData, forKey: .favoriteColor)
}
Copy the code

After the above work is done, we can have fun.

let taylor = Person(name: "Swift", favoriteColor: .blue)
let encoder = JSONEncoder(a)do {
    let encoded = try encoder.encode(taylor)
    let str = String(decoding: encoded, as: UTF8.self)
    print(str)
} catch {
    print(error.localizedDescription)
}
Copy the code

原文阅读:How to store NSCoding data using Codable