Swift 基于 NSUserDefaults、NSKeyedArchiver、ObjectMapper 存储简单键值对数据解决方案

开发过程中,我通常会有一些简单的数据存储,如果用数据库,又太重了,所以官方就有提供一些好用的API,方便我们使用。

NSUserDefaults(属性列表)
var userDefault = UserDefaults.standard

userDefault.set(URL(string: "http://github.com"), forKey: "domain")
var domain = userDefault.url(forKey: "domain")

userDefault.set("18", forKey: "age")
var age = userDefault.integer(forKey: "age")

userDefault.set(3.1415926535, forKey: "pi")
// 3.1415926535
var piDouble = userDefault.double(forKey: "pi")
// 3.141592
var piFloat = userDefault.float(forKey: "pi")

userDefault.set(true, forKey: "isLogin")
var isLogin = userDefault.bool(forKey: "isLogin")

userDefault.set(175.5, forKey: "height")
var height = userDefault.float(forKey: "height")

// 写入数据后,数据是先保存在内存中,然后再存储到硬盘上,所以如果遇到断电等行为,需要手动调用synchronize()
userDefault.synchronize()
NSUserDefaults 和 NSKeyedArchiver 实现存储对象
class People:NSObject,NSCoding,NSSecureCoding{
    static var supportsSecureCoding: Bool{
        return true
    }
    
    var name = ""
    var age = 0
    func encode(with aCoder: NSCoder) {
        aCoder.encode(self.name, forKey: "name")
        aCoder.encode(self.age, forKey: "age")
    }
    required init?(coder aDecoder: NSCoder) {
        self.name = aDecoder.decodeObject(forKey: "name") as! String
        self.age = aDecoder.decodeInteger(forKey: "age")
    }
    init(name:String,age:Int) {
        self.name = name
        self.age = age
    }
    override var description: String{
        return "name:\(name),age:\(age)"
    }
}

使用

do{
    let people = People(name: "Wiki",age: 18)
    let data = try NSKeyedArchiver.archivedData(withRootObject: people, requiringSecureCoding: false)
    userDefault.set(data, forKey: "people")
}catch{
    print(error)
}
do{
    let data = userDefault.object(forKey: "people") as! Data
    let people = try NSKeyedUnarchiver.unarchivedObject(ofClass: People.self, from: data)
    print(people!.description)
}catch{
    print(error)
}

NSUserDefaults 和 ObjectMapper 解决方案

NSKeyedArchiver 的使用相对来说比价复杂,我建议是引入一个第三方的库 ObjectMapper
,通过序列化为String,再从String 反序列化到 Object 简化对象的存储。

//  User.swift
import ObjectMapper
class User: Mappable {
    required init?(map: Map) {}
    func mapping(map: Map) {
        name <- map["name"]
        uid <- map["uid"]
    }
    var name:String = ""
    var uid:Int = 0
}

定义一个管理类,方便我们集中管理

//  MyUserDefaults.swift
import ObjectMapper

class MyUserDefaults{
    static let instance = MyUserDefaults()
    
    var loginUser:User?{
        set{setObject(newValue, forKey: "loginUser")}
        get{return getObject(User.self, forKey: "loginUser")}
    }
    var lastLoginType: Int{
        set{userDefault.set(newValue, forKey: "lastLoginType")}
        get{return userDefault.integer(forKey: "lastLoginType")}
    }
    
    private var userDefault = UserDefaults.standard
    private func setObject(_ newValue:T?,forKey:String){
        if(newValue == nil){
            userDefault.set("", forKey: forKey)
        }else{
            userDefault.set(newValue?.toJSONString(), forKey: forKey)
        }
    }
    private func getObject(_ type: T.Type,forKey:String) -> T?{
        let text = userDefault.string(forKey: forKey)
        if(text == nil || text?.count == 0){
            return nil
        }else{
            return Mapper().map(JSONString: text!)
        }
    }
}

使用方式

let user = MyUserDefaults.instance.loginUser
MyUserDefaults.instance.loginUser = User()

你可能感兴趣的:(Swift 基于 NSUserDefaults、NSKeyedArchiver、ObjectMapper 存储简单键值对数据解决方案)