天天看點

iOS資料持久化---NSCoding

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]實作已歸檔資料的重新載入,解碼。