使用 NSCoding 保存结构
Save a struct with NSCoding
我要保存以下数据:
class Book: NSObject, NSCoding {
var title: String
var chapter: [Chapter]
struct Chapter {
var chapTitle: String
var texte: [Texte]
}
struct Texte {
var description: String
var texte: [String]
var position: [Int]
var hidden: [Int?]
}
我目前正在使用 NSCoder 保存图书 class:
static let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!
static let ArchiveURL = DocumentsDirectory.appendingPathComponent("learn")
struct PropertyKey {
static let title = "title"
static let chapter = "Chapter"
}
//MARK: - Initialization
init?(title: String, chapter: [Book.Chapter]) {
self.title = title
self.chapter = chapter
}
//MARK: - NSCoding
func encode(with aCoder: NSCoder) {
aCoder.encode(title, forKey: PropertyKey.title)
aCoder.encode(chapter, forKey: PropertyKey.chapter)
}
required convenience init?(coder aDecoder: NSCoder) {
let title = aDecoder.decodeObject(forKey: PropertyKey.title) as! String
let chapter = aDecoder.decodeObject(forKey: PropertyKey.chapter) as! [Book.Chapter]
self.init(title: title, chapter: chapter)
}
有了这个我可以保存 Book 的 title
和一个空数组 chapter
。
然而,当我尝试将 chapTitle
和 texte
添加到 Book 对象时,出现以下错误:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x60000066dec0'
这是否意味着无法保存该结构?我应该改变什么?
如果可以将 book 设为 struct ,则最好使用 codable 。
struct Book: Codable {
var title: String
var chapter: [Chapter]
struct Chapter:Codable {
var chapTitle: String
var texte: [Texte]
}
struct Texte:Codable {
var description: String
var texte: [String]
var position: [Int]
var hidden: [Int?]
}
保存
static func saveData (books: [Book]) throws
{
let encoded = try JSONEncoder().encode(books)
try encoded.write(to: ArchiveURL)
print("Books saved")
}
检索
//retrive data from it's saved place
static func loadData() throws -> [Book]
{
let data = try Data(contentsOf: ArchiveURL)
return try JSONDecoder().decode([Book].self, from: data)
}
同时编辑顶部的变量
let directory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] + "/learn/"
let ArchiveURL = URL(fileURLWithPath: directory)
我要保存以下数据:
class Book: NSObject, NSCoding {
var title: String
var chapter: [Chapter]
struct Chapter {
var chapTitle: String
var texte: [Texte]
}
struct Texte {
var description: String
var texte: [String]
var position: [Int]
var hidden: [Int?]
}
我目前正在使用 NSCoder 保存图书 class:
static let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!
static let ArchiveURL = DocumentsDirectory.appendingPathComponent("learn")
struct PropertyKey {
static let title = "title"
static let chapter = "Chapter"
}
//MARK: - Initialization
init?(title: String, chapter: [Book.Chapter]) {
self.title = title
self.chapter = chapter
}
//MARK: - NSCoding
func encode(with aCoder: NSCoder) {
aCoder.encode(title, forKey: PropertyKey.title)
aCoder.encode(chapter, forKey: PropertyKey.chapter)
}
required convenience init?(coder aDecoder: NSCoder) {
let title = aDecoder.decodeObject(forKey: PropertyKey.title) as! String
let chapter = aDecoder.decodeObject(forKey: PropertyKey.chapter) as! [Book.Chapter]
self.init(title: title, chapter: chapter)
}
有了这个我可以保存 Book 的 title
和一个空数组 chapter
。
然而,当我尝试将 chapTitle
和 texte
添加到 Book 对象时,出现以下错误:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x60000066dec0'
这是否意味着无法保存该结构?我应该改变什么?
如果可以将 book 设为 struct ,则最好使用 codable 。
struct Book: Codable {
var title: String
var chapter: [Chapter]
struct Chapter:Codable {
var chapTitle: String
var texte: [Texte]
}
struct Texte:Codable {
var description: String
var texte: [String]
var position: [Int]
var hidden: [Int?]
}
保存
static func saveData (books: [Book]) throws
{
let encoded = try JSONEncoder().encode(books)
try encoded.write(to: ArchiveURL)
print("Books saved")
}
检索
//retrive data from it's saved place
static func loadData() throws -> [Book]
{
let data = try Data(contentsOf: ArchiveURL)
return try JSONDecoder().decode([Book].self, from: data)
}
同时编辑顶部的变量
let directory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] + "/learn/"
let ArchiveURL = URL(fileURLWithPath: directory)