Swift class和struct的解归档

NSCoding

这种方式是OC中就有的,比较老的方式,并且使用限制是只能是calss,然后实现NSCoding,对于struct是不能使用的。

internal func encode(with aCoder: NSCoder) {
        var count :UInt32 = 0
        if let ivar = class_copyIvarList(self.classForCoder, &count) {
            for i in 0.. c语言字符串
                if let cName = ivar_getName(iv) {
                    //转换成String字符串
                    guard let strName = String(cString: cName, encoding: String.Encoding.utf8) else{
                        //继续下一次遍历
                        continue
                    }
                    //利用kvc 取值
                    let value = self.value(forKey: strName)
                    aCoder.encode(value, forKey: strName)
                }
            }
            // 释放c 语言对象
            free(ivar)
        }
    }
    
    internal required init?(coder aDecoder: NSCoder) {
        super.init()
        var count :UInt32 = 0
        if let ivar = class_copyIvarList(self.classForCoder, &count) {
            for i in 0..

利用运行时设置好属性,这样又多了一层限制,必须继承NSObject,因为运行时只有继承NSObject才会具备。如果不介意手动一行一行设置属性,那大可不继承NSObject。

static func saveCustomObject(customObject object: NSCoding, key: String) {
        let encodedObject = NSKeyedArchiver.archivedData(withRootObject: object)
        self.userDefaults.set(encodedObject, forKey: key)
        self.userDefaults.synchronize()
    }
    
    static func removeCustomObject(key: String) {
        self.userDefaults.removeObject(forKey: key)
    }
    
    static func getCustomObject(forKey key: String) -> Any? {
        if let decodedObject = self.userDefaults.object(forKey: key), let data = decodedObject as? Data {
            let object = NSKeyedUnarchiver.unarchiveObject(with: data)
            return object
        }
        return nil
    }

这样就把class归档,解档做好了,对于struct的归档必须使用取巧的方式参考这里或者这里面,NSCoding只适用于class,系统并没有提供专门的针对struct的解归档的协议.

Swift4.0后Codable

Swift4.0后解归档就变得容易多了Codable,这个协议对于class或是struct都适用,并且使用起来很简单方便。

class ClassA: Codable {
    private var message : String? = "message"
    private var nu : String? = "nu"
    private var condition : String? = "condition"
    var com : String? = "com"
    var status : String? = "status"
    var state : String? = "state"
    var data : [ClassB]? = []
}

struct ClassB: Codable{
    var time : String? = "time"
    var ftime : String? = "ftime"
    var context : String? = "context"
    var location : String? = "location"
}

定义class和struct,只要声明实现Codable协议,不需要做额外的其他操作,比如不需要手动添加设置解归档的key等等。系统都会帮你搞定。不过需要注意的是Codable并不支持继承方式的子类解归档,也就是如果ClassC继承ClassA,如果对ClassC解归档时不会成功的,也就是说Codable不能够被继承使用,所以只能在子类实现Codable,父类不去实现Codable。

let a = ClassA()
        let b = ClassB()
        a.data = [b]
        //归档
        let encoder = JSONEncoder()
        if let data = try? encoder.encode(a) {
            print(String(data: data, encoding: .utf8)!)
            UserDefaults.standard.set(data, forKey: "piaojin")
        }
        
        let object = UserDefaults.standard.object(forKey: "piaojin")
        //解档
        let decoder = JSONDecoder()
        if let data = object as? Data {
            let objectA = try? decoder.decode(ClassA.self, from: data)
            print("\(String(describing: objectA))")
        }

这样就搞定了,关于Codable的详细介绍可以参考这里和这里。

你可能感兴趣的:(Swift class和struct的解归档)