美文网首页程序员iOS DeveloperiOS技术点
Swift3.0中如何使用RunTime对数据进行归档和反归档

Swift3.0中如何使用RunTime对数据进行归档和反归档

作者: Fluent | 来源:发表于2016-06-06 16:36 被阅读810次

在开发中我们经常会遇到要把数据保存到本地,在iOS中数据持久化的方法基本上有以下5种:
1.writeToFile;
2.NSUserDefults;
3.NSCoding(归档/反归档);
4.sqlite;
5.coreData。
今天小编主要介绍第三种:
首先创建一个model继承NSObject,并且遵守NSCoding协议和实现它的两个方法。以下是不使用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写的,有一些问题,现在已更新3.0

直接看代码

class LCBaseModel: NSObject, NSCoding {
    // 使用runtime属性前面必须加dynamic,并且是不可选类型,意思是允许动态更新属性
    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)
    }

总结:

  1. 在swift中不需要引入runtime文件,系统默认就引入了;
  2. 属性前面加dynamic,并且不可选。

相关文章

网友评论

    本文标题:Swift3.0中如何使用RunTime对数据进行归档和反归档

    本文链接:https://www.haomeiwen.com/subject/aozrdttx.html