美文网首页
[Q] Swift 4.0 中的对象序列化

[Q] Swift 4.0 中的对象序列化

作者: 流火绯瞳 | 来源:发表于2018-02-02 10:15 被阅读519次

对象序列化作为常用的数据本地化方法之一,经常用来保存用户信息等,其序列化方法也很简单,只需要实现NSCoding协议,实现其协议方法即可!
但当我们的对象属性比较多的时候,就会显现出一些不方便了,但这在Swift 4.0中就变得相当方便了。

Swift 3.0 之前的方式

Swift 3.0之前的方式,和OC中的序列化方式相同,先实现NSCoding协议,然后实现其协议方法,在其协议方法中分别对各个属性进行encode和decode操作,以保存用户信息为例:

需要注意:这里的对象需要继承自NSObject;

// 使用NSCoding进行序列化
class LQUser: NSObject, NSCoding {
    
    var name: String = ""
    var age: Int32 = 0
    var psw: String = ""
    
    static var user: LQUser {
        
        let ud = UserDefaults.standard
        guard let data = ud.data(forKey: "lqUser_savedData") else {
            // 如果获取失败则重新创建一个返回
            return LQUser()
        }
        
        guard let us = NSKeyedUnarchiver.unarchiveObject(with: data) as? LQUser else { return LQUser() }
        
        return us
    }
    
    func encode(with aCoder: NSCoder) {
        aCoder.encode(name, forKey: "name")
        aCoder.encode(age, forKey: "age")
        aCoder.encode(psw, forKey: "psw")
    }
    
    private override init() {
        super.init()
        
    }
    
    required init?(coder aDecoder: NSCoder) {
        if let rs = aDecoder.decodeObject(forKey: "name") as? String {
            name = rs
        }
        
        if let rs = aDecoder.decodeObject(forKey: "psw") as? String {
            psw = rs
        }
        
        age =  aDecoder.decodeInt32(forKey: "age")
    }
    
    func saved() {
        
        let us = UserDefaults.standard
        let data = NSKeyedArchiver.archivedData(withRootObject: self)
        us.set(data, forKey: "lqUser_savedData")
        us.synchronize()
    }
    
}

以上代码也比简单,都能看明白,使用的时候不用调用其初始化方法,只需要直接调用其类属性user即可:

let user = LQUser.user
       
       user.age = 28
       user.name = "流火绯瞳"
       user.psw = "123456"
       
       user.saved()

在给各个属性赋值之后,调用其保存方法saved()即可!
取值的时候,也是调用user:

let user = LQUser.user
 
print(user.name)

看上去也挺简单的,是的,当属性少的时候,是不复杂;但是,如果你要序列化的一个对象包含N多个属性,你就要对这N多个属性分别写一遍encode与decode,难度不大,简单谈不上,只是一些重复的操作,且不易维护!

Swift 4.0新的协议 Codable

在Swift 4.0中新出的协议 Codable 就可以避免上面的方式中的问题,而且使用也十分简单:

// swift 4.0 新协议 Codable
class LQUser: NSObject, Codable {
    var name: String = ""
    var age: Int = 0
    var psw = ""
    
    static var user: LQUser {
        
        let ud = UserDefaults.standard
        guard let data = ud.data(forKey: "lqUser_savedData") else {
            // 如果获取失败则重新创建一个返回
            return LQUser()
        }
        
        guard let us = try? JSONDecoder().decode(self, from: data) else {
            return LQUser()
        }
        
        return us
    }

    private override init() {
        super.init()
    }

    func saved() {

        if let data = try? JSONEncoder().encode(self) {

            let us = UserDefaults.standard

            us.set(data, forKey: "lqUser_savedData")
            us.synchronize()
        }
    }
}

这里使用的是 JSONEncoder / JSONDecoder 进行编解码,也可以选择使用其他的方式,但是不能使用NSKeyedArchiver / NSKeyedUnarchiver。

使用的时候同第一种:

// 存
let user = LQUser.user

        user.age = 28
        user.name = "流火绯瞳"
        user.psw = "123456"
        
        user.saved()

取:

let user = LQUser.user
        
print(user.name)

另外,这里的类也是继承自NSObject的,也可以不继承:

class LQUser: Codable {
    var name: String = ""
    var age: Int = 0
    var psw = ""
    
    static var user: LQUser {
        
        let ud = UserDefaults.standard
        guard let data = ud.data(forKey: "lqUser_savedData") else {
            // 如果获取失败则重新创建一个返回
            return LQUser()
        }
        
        guard let us = try? JSONDecoder().decode(self, from: data) else {
            return LQUser()
        }
        
        return us
    }

    private init() {
       
    }

    func saved() {

        if let data = try? JSONEncoder().encode(self) {

            let us = UserDefaults.standard

            us.set(data, forKey: "lqUser_savedData")
            us.synchronize()
        }
    }
}

甚至也可以是结构体:

// swift 4.0 新协议 Codable
struct LQUser: Codable {
    var name: String = ""
    var age: Int = 0
    var psw = ""
    
    static var user: LQUser {
        
        let ud = UserDefaults.standard
        guard let data = ud.data(forKey: "lqUser_savedData") else {
            // 如果获取失败则重新创建一个返回
            return LQUser()
        }
        
        guard let us = try? JSONDecoder().decode(self, from: data) else {
            return LQUser()
        }
        
        return us
    }

    private init() {
       
    }

    func saved() {

        if let data = try? JSONEncoder().encode(self) {

            let us = UserDefaults.standard

            us.set(data, forKey: "lqUser_savedData")
            us.synchronize()
        }
    }
}

可以发现其便利性,不仅可存储的类型多了,主要的还是不用对每个属性去分别encode与decode。

相关文章

网友评论

      本文标题:[Q] Swift 4.0 中的对象序列化

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