struct AboutMe {
var detail: String
var links: [[String : String]]
}
在Swift中嗅绸,Struct類型是無(wú)法進(jìn)行歸檔操作的,只有繼承自NSObject并且遵守了NSCoding協(xié)議的類才可以進(jìn)行相應(yīng)的歸檔操作断国。也就是將上面結(jié)構(gòu)體改成類:
class AboutMe: NSObject, NSCoding {
var detail: String
var links: [[String : String]]
required init?(coder aDecoder: NSCoder) {
aDecoder.decodeObjectForKey("detail")
aDecoder.decodeObjectForKey("links")
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(detail)
aCoder.encodeObject(links)
}
}
但是如果要對(duì)Struct進(jìn)行歸檔贤姆,可以轉(zhuǎn)換思維,使用按照以下步驟實(shí)現(xiàn)稳衬。
實(shí)現(xiàn)一個(gè)歸檔霞捡、解檔協(xié)議:
public protocol Archivable {
func archive() -> NSDictionary
init?(unarchive: NSDictionary?)
}
因?yàn)镹SKeyedArchiver可以直接對(duì)Foundation類進(jìn)行操作,所以可以將結(jié)構(gòu)體中的屬性都轉(zhuǎn)換成字典薄疚,然后進(jìn)行后續(xù)操作碧信;archive函數(shù)返回一個(gè)歸檔好的字典,而可失敗構(gòu)造函數(shù)傳入一個(gè)需要解檔的字典街夭。
讓AboutMe遵守并實(shí)現(xiàn)以上聲明的協(xié)議
extension AboutMe: Archivable{
func archive() -> NSDictionary {
return ["detail" : detail, "links" : links]
}
init?(unarchive: NSDictionary?) {
guard let values = unarchive else { return nil }
if let detail = values["detail"] as? String,
links = values["links"] as? [[String : String]] {
self.detail = detail
self.links = links
} else {
return nil
}
}
}
這里使用擴(kuò)展進(jìn)行歸解檔方法的添加砰碴,可以看到,原先結(jié)構(gòu)體的屬性在接口上都是以字典的形勢(shì)在傳輸板丽。
實(shí)現(xiàn)歸解檔函數(shù)
public func unarchiveObjectWithFile<T: Archivable>(path: String) -> T? {
return T(unarchive: NSKeyedUnarchiver.unarchiveObjectWithFile(path) as? NSDictionary)
}
public func archiveObject<T: Archivable>(object: T, toFile path: String) {
NSKeyedArchiver.archiveRootObject(object.archive(), toFile: path)
}
對(duì)AboutMe進(jìn)行字典化后呈枉,NSKeyedArchiver可以直接對(duì)其進(jìn)行操作,所以這個(gè)實(shí)現(xiàn)并不復(fù)雜檐什。
完成以上步驟碴卧,就可以對(duì)Struct進(jìn)行歸檔和接檔操作了:
let path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomainMask.UserDomainMask, true).first! + "/AboutMe"
let aboutMe = AboutMe(detail: "tripleCC", links: [["github" : "https://github.com/tripleCC"], ["gitblog" : "http://triplecc.github.io/"]])
archiveObject(aboutMe, toFile: path)
let unAboutMe: AboutMe? = unarchiveObjectWithFile(path)
debugPrint(unAboutMe)
如果要進(jìn)行集合操作,可以添加以下函數(shù):
public func archiveObjectLists<T: Archivable>(lists: [T], toFile path: String) {
let encodedLists = lists.map{ $0.archive() }
NSKeyedArchiver.archiveRootObject(encodedLists, toFile: path)
}
public func unarchiveObjectListsWithFile<T: Archivable>(path: String) -> [T]? {
guard let decodedLists = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as? [NSDictionary] else { return nil }
return decodedLists.flatMap{ T(unarchive: $0) }
}
參考博客
1.NSCoding And Swift Structs
2.Property Lists And User Defaults in Swift