如果自定义类型需要存放到UserDefaults
中需要自定义类型继承NSObject
以及NSCoding
、NSSecureCoding
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?
网友评论