NSCoding(NSSucureCoding)归档自定义cla

2019-09-28  本文已影响0人  林夕copy

如果自定义类型需要存放到UserDefaults中需要自定义类型继承NSObject以及NSCodingNSSecureCoding

NSSecureCoding继承自NSCoding,只用实现其中一个

public protocol NSCoding {
    public func encode(with aCoder: NSCoder)

    public init?(coder aDecoder: NSCoder) // NS_DESIGNATED_INITIALIZER
}

public protocol NSSecureCoding : NSCoding {

    
    // This property must return YES on all classes that allow secure coding. Subclasses of classes that adopt NSSecureCoding and override initWithCoder: must also override this method and return YES.
    // The Secure Coding Guide should be consulted when writing methods that decode data.
    public static var supportsSecureCoding: Bool { get }
}

以下是我自定义的class

class People: NSObject, NSSecureCoding {
    static var supportsSecureCoding: Bool = true
    enum CodeKey: String {
        case nameKey = "name"
        case ageKey = "age"
        case dogKey = "dog"
    }
    
    var name: String = ""
    var age: Int = 0
    var dog: Dog
    
    override init() {
        name = "123"
        age = 1
        dog = Dog(name: "lanbo", age: 2)
    }
    
    func encode(with aCoder: NSCoder) {
        aCoder.encode(name, forKey: CodeKey.nameKey.rawValue)
        aCoder.encode(age, forKey: CodeKey.ageKey.rawValue)
        aCoder.encode((try? JSONEncoder().encode(dog)) ?? Data())
    }
    
    required init?(coder aDecoder: NSCoder) {
        name = aDecoder.decodeObject(forKey: CodeKey.nameKey.rawValue) as? String ?? ""
        age = aDecoder.decodeInteger(forKey: CodeKey.ageKey.rawValue)
        dog = try! JSONDecoder().decode(Dog.self, from: aDecoder.decodeData() ?? Data())
    }
}


struct Dog: Codable {
    var name: String
    var age: Int
}

使用UserDefaults进行存取

let albert = People()
let obj = try? NSKeyedArchiver.archivedData(withRootObject: albert, requiringSecureCoding: false)
UserDefaults.standard.set(obj, forKey: "albert")
UserDefaults.standard.synchronize()
if let per = UserDefaults.standard.object(forKey: "albert") as? Data {
    let p = try! NSKeyedUnarchiver.unarchivedObject(ofClass: People.self, from: per)
    print(p?.dog) //Optional(CacheDemo.Dog(name: "lanbo", age: 2))
}
        

单独存取struct时也可以直接用Codable协议把结构体转化成Data后存储

let dog = Dog(name: "333", age: 3)
let pp = try? JSONEncoder().encode(dog)
UserDefaults.standard.set(pp, forKey: "dog")
UserDefaults.standard.synchronize()
        
if let d = UserDefaults.standard.object(forKey: "dog") as? Data {
    if let dd = try? JSONDecoder().decode(Dog.self, from: d) {
         print(dd.name) // 333
    }
}

其中NSKeyedUnarchiver.unarchivedObject这个方法需要实现NSSecureCoding才能够使用,NSCoding应该使用NSKeyedUnarchiver.unarchiveObject(with: Data)但是这个方法在iOS12废弃了,应该是苹果推荐使用NSSecureCoding.

@available(iOS, introduced: 2.0, deprecated: 12.0, message: "Use +unarchivedObjectOfClass:fromData:error: instead")
    open class func unarchiveObject(with data: Data) -> Any?
上一篇 下一篇

猜你喜欢

热点阅读