将归档简单封装为一个类,在使用归档的时候,只需要将需要归档的模型继承于PYArchiverObject,并调用方法即可。
1.遵守NSCoding协议
@objcMembers
class PYArchiverObject : NSObject,NSCoding{
required override init() {}
func encode(with coder: NSCoder) {
let mirror = Mirror.init(reflecting: self)
for child in mirror.children {
if let propertyKey = child.label{
coder.encode(child.value, forKey: propertyKey)
}
}
}
required init?(coder: NSCoder) {
super.init()
let mirror = Mirror.init(reflecting: self)
var propertyDic :[String : Any?] = [:]
for child in mirror.children {
if let propertyKey : String = child.label , let propertyValue = coder.decodeObject(forKey: propertyKey){
propertyDic[propertyKey] = propertyValue
self.setValue(propertyValue, forKey: propertyKey)
}
}
}
}
注:在解码协议实现中,使用到setValueForKey方法,该方法为objc方法,需要对象为objc对象,所以将类申明为@objcMembers.并且在继承的类中不可以使用optional类型(例子:String?)。如果有需要可删除该方法,使用自己的方式赋值即可。
2.归档
/// 归档路径
/// - Returns: ~
static func filePath () -> String?{
if let basePath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first{
let className = String(describing: type(of: self))
return basePath.appending("/\(className)")
}
return nil
}
/// 归档
func archived(requiringSecureCoding:Bool = false){
let selfClass = type(of: self)
guard let filePath = selfClass.filePath() else {
return
}
if #available(iOS 11.0, *) {
do{
let fileUrl = URL(fileURLWithPath: filePath)
let data :Data = try NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: requiringSecureCoding)
try data.write(to: fileUrl, options: .atomic)
}
catch let error{
print("归档失败\(error)")
}
} else {
if !NSKeyedArchiver.archiveRootObject(self, toFile: filePath){
print("归档失败.")
}
}
}
/// 解档
/// - Returns: ~
static func unarchived() -> Self?{
guard let filePath = self.filePath() else {
return nil
}
if #available(iOS 11.0, *) {
do{
let fileUrl = URL(fileURLWithPath: filePath)
let data = try Data.init(contentsOf: fileUrl)
let unarchiverModel = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? Self
return unarchiverModel
}
catch let error{
print("解档失败:\(error)")
}
} else {
if let unarchiverModel = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as? Self{
return unarchiverModel
}
else{
print("解档失败.")
}
}
return nil
}
3.例子
class UserInfo : PYArchiverObject,HandyJSON{
var id : Int = 0 //id
var avatar : String = "" //头像
var nickname : String = "" //用户昵称
var phone : String = "" //手机号
var username : String = "" //姓名
}
func test(){
let testDic : Dictionary<String,Any> = ["id":"用户ID",
"avatar":"头像地址",
"phone":"电话号码",
"username":"4444"]
let userInfoModel = UserInfo.deserialize(from: testDic)
userInfoModel?.archived()
}
建议:在使用的过程中,配合第三方HandyJSON库使用,将服务器返回的json直接转化为model,调用归档方法。