Мне нужно читать/записывать свойства, которые являются Codable (например, Date) и NSCoding (например, NSMutableAttributedString) из/в файл в формате JSON. Изучив, как читать и записывать файлы с помощью Codable, как делать это в формате JSON и как комбинировать NSCoding с Codable, когда некоторые свойства не соответствуют Codable (но соответствуют NSCoding), я собрался вместе следующий код и запутался в процессе.
Наконец-то я понял, как это проверить, и внес соответствующие изменения. Но мне все же хотелось бы знать, как три типа декодера/кодировщика (NSCoding, Codable и JSON) взаимодействуют или заменяют друг друга.
import Foundation
class Content: Codable {
// Content
var attrStr = NSMutableAttributedString(string: "")
var date: Date?
// Initializer for content
init(attrStr: NSMutableAttributedString, date: Date) {
self.attrStr = attrStr
self.date = date
}
// Need to explicitly define because NSMutableAttributedString isn't codable
enum CodingKeys: String, CodingKey {
case attrStr
case date
}
// Need to explicitly define the decoder. . . .
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
date = try container.decode(Date.self, forKey: .date)
let attrStrData = try container.decode(Data.self, forKey: .attrStr)
attrStr = NSKeyedUnarchiver.unarchiveObject(with: attrStrData) as? NSMutableAttributedString ?? NSMutableAttributedString(string: "Error!")
}
// Need to explicitly define the encoder. . . .
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(date, forKey: .date)
let attrStrData = NSKeyedArchiver.archivedData(withRootObject: attrStr)
try container.encode(attrStrData, forKey: .attrStr)
}
static func getFileURL() -> URL {
// Get the directory for the file
let docsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
// Get the full path and filename
return docsDir.appendingPathComponent("contentArray").appendingPathExtension("cntnt")
}
static func saveToFile(content: [Content]) {
// Get the file's URL
let fileURL = getFileURL()
do {
// Encode the data
let data = try JSONEncoder().encode(content)
// Write to a/the file
try data.write(to: fileURL)
} catch {
print("Could not encode or save to the file!")
}
}
static func loadFromFile() -> [Content] {
// Get the file's URL
let fileURL = getFileURL()
do {
// Read from the file
let data = try Data(contentsOf: fileURL)
// Decode the data
return try JSONDecoder().decode([Content].self, from: data)
} catch {
print("Could not decode or read from the file!")
return []
}
}
}
NSMutableAttributedString
, которая может выглядеть лучше, но не должна меняться, работает она или нет. - person Fabian   schedule 19.08.2018NSCoding
может работать, только если класс наследуется отNSObject
и принимаетNSCoding
- person vadian   schedule 19.08.2018