在开发中我们经常会遇到要把数据保存到本地,在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)
}
总结:
- 在swift中不需要引入runtime文件,系统默认就引入了;
- 属性前面加dynamic,并且不可选。