1.資料模型:在傳統的類定義基礎上,加上(1)資料存儲位址ArchiveURL(2)繼承NSObject,遵從NSCoding協定(實作用于将資料編碼的func encode(with aCoder: NSCoder),實作将歸檔資料恢複為類資料對象的required convenience init?(coder aDecoder: NSCoder)。) 隻用遵從NSCoding協定的類才能被編碼歸檔。
import UIKit
import os.log
class Country:NSObject,NSCoding {
//MARK:Property
let name:String
var nationalFlagImage:UIImage
var capital:String
var mainCities:[String]
//MARK:建立資料存儲的url路徑
//(1)使用FileManager對象,獲得使用者域的通用目錄的url
static let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!
//(2)建立用于存儲的url路徑:在DocumentsDirectory基礎上,加上路徑元素,相當于在DocumentsDirectory路徑下,建立了一個檔案 夾,用于存放資料
static let ArchiveURL = DocumentsDirectory.appendingPathComponent("countries")
init(name:String,nationalFlagImage:UIImage,capital:String,mainCities:[String]) {
self.name = name
self.nationalFlagImage = nationalFlagImage
self.capital = capital
self.mainCities = mainCities
//這句話時初始化父類NSObject
super.init()
}
///持久化相關代碼
//(1)為Country類中的所有屬性設定相應的鍵名,類似于資料裡面的屬性名
struct PropertyKey {
static let name = "name"
static let nationalFlagImage = "nationalFlagImage"
static let capital = "capital"
static let mainCities = "mainCities"
}
//(2)讓Country類繼承 NSObject 類,并實作 NSCoding 協定
// 繼承了 NSObject 類,需要在本類初始化時,完成父類的初始化
// NSCoding協定需要實作 encode 函數和 init?初始化函數
// 為每個屬性綁定相應的鍵名,以鍵名編碼
func encode(with aCoder: NSCoder){
aCoder.encode(name, forKey: PropertyKey.name)
aCoder.encode(nationalFlagImage, forKey: PropertyKey.nationalFlagImage)
aCoder.encode(capital, forKey: PropertyKey.capital)
aCoder.encode(mainCities, forKey: PropertyKey.mainCities)
}
// 以鍵名解碼
required convenience init?(coder aDecoder: NSCoder){
guard let name = aDecoder.decodeObject(forKey: PropertyKey.name) as? String else {
os_log("無法完成解碼", log: .default, type: .debug)
return nil
}
guard let nationalFlagImage = aDecoder.decodeObject(forKey: PropertyKey.nationalFlagImage) as? UIImage else {
os_log("無法完成解碼", log: .default, type: .debug)
return nil
}
guard let capital = aDecoder.decodeObject(forKey: PropertyKey.capital) as? String else {
os_log("無法完成解碼", log: .default, type: .debug)
return nil
}
guard let mainCities = aDecoder.decodeObject(forKey: PropertyKey.mainCities) as? [String] else {
os_log("無法完成解碼", log: .default, type: .debug)
return nil
}
self.init(name: name, nationalFlagImage: nationalFlagImage, capital: capital, mainCities: mainCities)
}
}
2. 使用 NSKeyedArchiver.archiveRootObject(countries, toFile: Country.ArchiveURL.path)實作Country數組資料的歸檔存儲。
使用 NSKeyedUnarchiver.unarchiveObject(withFile: Country.ArchiveURL.path) as? [Country]實作已歸檔資料的重新載入,解碼。