Первая проблема: Я пытался использовать контейнер без ключей, и это не имеет смысла, потому что мне определенно нужен контейнер с ключами, потому что у меня есть 2 атрибута (name
и details
** 1008).
Итак, мне нужно было реализовать некоторые CodingKey
и использовать метод decoder.container(keyedBy:)
.
Вторая проблема: после некоторых экспериментов я заметил, что могу превратить NSAttributedString
в Data
, просто используя NSKeyedArchiver
! Data
- это Codable
, поэтому я могу его кодировать и декодировать.
Итак, окончательное решение, которое я получил:
class CoachProgram: Codable {
var name: String
var details: NSAttributedString
enum CodingKeys: String, CodingKey {
case name
case details
}
init(name: String, details: NSAttributedString) {
self.name = name
self.details = details
}
required public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let name = try container.decodeIfPresent(String.self, forKey: .name) {
self.name = name
}
if let data = try container.decodeIfPresent(Data.self, forKey: .details) {
self.details = NSKeyedUnarchiver.unarchiveObject(with: data) as? NSAttributedString ?? NSAttributedString()
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(name, forKey: .name)
try container.encode(NSKeyedArchiver.archivedData(withRootObject: details), forKey: .details)
}
}
В действии:
let coachProgram = CoachProgram(name: "John Doe", details: NSAttributedString())
let archiver = NSKeyedArchiver()
do {
try archiver.encodeEncodable(coachProgram, forKey: NSKeyedArchiveRootObjectKey)
}
catch {
print(error)
}
UserDefaults.standard.set(archiver.encodedData, forKey: "CoachProgram")