本文为CocoaChina网友desty投稿
概述:
UserDefaults:Key-Value持久化的方案,适合用来保存配置数据,简单的用户信息,或者一些状态数据(大批量数据还是要考虑使用DB)
Archiver:对象类型无法直接进行持久化,需要对象遵循序列化的协议。
UserDefaults使用:
UserDefaults.standard.set(value, forKey: String)
Archiver使用:
Object-C / Swift3中需要实现NSCoding协议:
class Person: NSObject, NSCoding { public func encode(with aCoder: NSCoder) { // 需根据属性自己实现 } public required init?(coder aDecoder: NSCoder) { // 需根据属性自己实现 } } let personData = NSKeyedArchiver.archivedData(withRootObject: Person())
下面是通过OC的runtime机制实现的动态实现NSCoding协议,想要某个类支持NSCoding协议,只需要继承CodingSupport即可。
open class CodingSupport: NSObject, NSCoding { public func encode(with aCoder: NSCoder) { var count: UInt32 = 0 let ivars = class_copyIvarList(self.classForCoder, &count) for i in 0..Swift4中实现简单很多,只需要支持Codable协议:
class Person: Codable { } let encoder = JSONEncoder() let personData = try? encoder.encode(Person())上面介绍了些关于UserDefaults和Archiver的用法,但这并不是本文的主题,本文的主题是将两者融合用在实际项目中,
1. 解决UserDefaults在存储数据时出现的代码分散,不易管理
2. 在多个用户间切换时,数据持久化的问题。
案例1:用户A信息需要存储,推荐做法
class User: Codable { var name = "default name" var mask = "defalut mask" var age = 0 var gendar = 0 var level = 0 var status = 0 } // 存储 let user = User() let encoder = JSONEncoder() let encoded = try? encoder.encode(user) UserDefaults.standard.set(encoded, forKey: "UserA") UserDefaults.standard.synchronize() // 获取 let infoData = UserDefaults.standard.object(forKey: "UserA") guard let info = infoData as? Data else { return nil } let decoder = JSONDecoder() let decoded = try? decoder.decode(T.self, from: info)假如此时切换到了用户B,并存储B的相关信息,我们需要在UserDefaults时设置是使用不同的key。
关于这些操作的封装有一个框架PieceStore,github地址: https://github.com/ZeroFengLee/PieceStore,这个框架对Model数据的存储做了很好的封装。