Swift3.0中如何使用RunTime對數(shù)據(jù)進行歸檔和反歸檔

在開發(fā)中我們經(jīng)常會遇到要把數(shù)據(jù)保存到本地,在iOS中數(shù)據(jù)持久化的方法基本上有以下5種:
1.writeToFile;
2.NSUserDefults;
3.NSCoding(歸檔/反歸檔);
4.sqlite;
5.coreData。
今天小編主要介紹第三種:
首先創(chuàng)建一個model繼承NSObject,并且遵守NSCoding協(xié)議和實現(xiàn)它的兩個方法。以下是不使用runtime和使用runtime的對比:

不使用runtime寫法

    // 歸檔
    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(name, forKey: "name")
        aCoder.encodeObject(age, forKey: "age")
        aCoder.encodeObject(number, forKey: "number")
    }
    // 反歸檔
    required init?(coder aDecoder: NSCoder) {
        super.init()
        name = aDecoder.decodeObjectForKey("name") as? String
        age = aDecoder.decodeObjectForKey("age") as? Int
        number = aDecoder.decodeObjectForKey("number") as? NSNumber
    }

使用runTime寫法

之前是Swift2.0寫的,有一些問題,現(xiàn)在已更新3.0

直接看代碼

class LCBaseModel: NSObject, NSCoding {
    // 使用runtime屬性前面必須加dynamic,并且是不可選類型,意思是允許動態(tài)更新屬性
    dynamic var name = ""
    dynamic var age = 0
    
    override init() {
        
    }
    
    // 歸檔
    func encode(with aCoder: NSCoder) {
        var count: UInt32 = 0
        guard let ivars = class_copyIvarList(self.classForCoder, &count) else {
            return
        }
        for i in 0 ..< count {
            let ivar = ivars[Int(i)]
            let name = ivar_getName(ivar)
            
            let key = NSString.init(utf8String: name!) as! String

            if let value = self.value(forKey: key) {
                aCoder.encode(value, forKey: key)
            }
        }
        // 釋放ivars
        free(ivars)
    }

    // 反歸檔
    required init?(coder aDecoder: NSCoder) {
        super.init()
        var count: UInt32 = 0
        guard let ivars = class_copyIvarList(self.classForCoder, &count) else {
            return
        }
        for i in 0 ..< count {
            let ivar = ivars[Int(i)]
            let name = ivar_getName(ivar)
            let key = NSString.init(utf8String: name!) as! String
            if let value = aDecoder.decodeObject(forKey: key) {
                self.setValue(value, forKey: key)
            }
        }
        // 釋放ivars
        free(ivars)
    }
    
}

下面是使用

    override func viewDidLoad() {
        super.viewDidLoad()
        let model = LCBaseModel()
        model.name = "FlyChang"
        model.age = 25
        
        var path = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).last
        path = path! + "/Model"
        let data = NSMutableData()
        let archiver = NSKeyedArchiver.init(forWritingWith: data)
        archiver.encode(model, forKey: "model")
        archiver.finishEncoding()
        data.write(toFile: path!, atomically: true)
        
        let data1 = NSData(contentsOfFile: path!)
        let una = NSKeyedUnarchiver.init(forReadingWith: data1! as Data)
        let m = una.decodeObject(forKey: "model") as! LCBaseModel
        una.finishDecoding()
        print("-----------runtime-----")
        print(m.name)
        print(m.age)
    }

總結(jié):

  1. 在swift中不需要引入runtime文件,系統(tǒng)默認就引入了;
  2. 屬性前面加dynamic,并且不可選。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容