正如大家所知,Swift中的結構體不遵守NSCoding協議。NSCoding只適用于繼承自NSObject的類。可是結構體在Swift中的地位與使用頻率都非常高,因此,我們需要一個能將結構體的實例歸檔和解檔的方法。
Janie寫過在Sonoplot工作時,他們團隊對此的解決方法。
簡而言之,他們定義了一個擁有兩個方法的協議:一個方法可以從結構體當中獲得一個NSDictionary,另一個方法可以使用NSDictionary來初始化一個結構體。接著,再使用NSKeyedArchiver對這個NSDictionary進行序列化。這個方案的優雅之處在于,只要遵守了這個協議的結構體都可以進行序列化。
我近靈光一閃,想到了另一種解決方案。盡管我已經實現了這種方案,并且使用它開發過幾個小項目,但是我還是不確定這是不是一個好的方案。這個方法的優雅程度無法與上面提到的方法相提并論。然而我還是將它寫出來,讓讀者自己來進行判斷。
假設我們有一個person結構體:
[cpp] view plaincopy
struct Person {
let firstName: String
let lastName: String
}
我們不能使這個結構體遵守NSCoding協議,但是我們可以在結構體當中增加一個類的定義,使這個類來遵守NSCoding協議:
[cpp] view plaincopy
extension Person {
class HelperClass: NSObject, NSCoding {
var person: Person?
init(person: Person) {
self.person = person
super.init()
}
class func path() -> String {
let documentsPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).first
let path = documentsPath?.stringByAppendingString("/Person")
return path!
}
required init?(coder aDecoder: NSCoder) {
guard let firstName = aDecoder.decodeObjectForKey("firstName") as? String else { person = nil; super.init(); return nil }
guard let laseName = aDecoder.decodeObjectForKey("lastName") as? String else { person = nil; super.init(); return nil }
person = Person(firstName: firstName, lastName: laseName)
super.init()
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(person!.firstName, forKey: "firstName")
aCoder.encodeObject(person!.lastName, forKey: "lastName")
}
}
}
發生了什么呢?我們在Person結構體當中增加了一個類,并使它遵守了NSCoding協議,這也意味著這個類需要實現init?(coder aDecoder: NSCoder)和encodeWithCoder(aCoder: NSCoder)方法。這個類擁有一個類型為Person的屬性,并且在encodeWithCoder(aCoder: NSCoder)方法中將這個結構體實例的值都進行了歸檔,同時在init?(coder aDecoder: NSCoder)中進行解檔,并創建了一個新的person實例。
接下來要做的事就是向 Person 結構體的定義中增加歸檔和解檔的方法:
[cpp] view plaincopy
struct Person {
let firstName: String
let lastName: String
static func encode(person: Person) {
let personClassObject = HelperClass(person: person)
NSKeyedArchiver.archiveRootObject(personClassObject, toFile: HelperClass.path())
}
static func decode() -> Person? {
let personClassObject = NSKeyedUnarchiver.unarchiveObjectWithFile(HelperClass.path()) as? HelperClass
return personClassObject?.person
}
}
在這段代碼中,我們創建了一個HelperClass對象來幫助進行歸檔和解檔。
這個結構體的使用方法應該是這樣的:
[cpp] view plaincopy
let me = Person(firstName: "Dominik", lastName: "Hauser")
Person.encode(me)
let myClone = Person.decode()
firstNameLabel.text = myClone?.firstName
lastNameLabel.text = myClone?.lastName
你可以在Github上找到完整的代碼。
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。