人在江湖飄,總免不了要存一些值到UserDefaults。swift
UserDefaults.standard.set("@沒故事的卓同窗", forKey: "Author")
let author = UserDefaults.standard.value(forKey: "Author")複製代碼
有存就有取,還可能有不少地方會取這個值。這樣的話每次寫這個 key 就有點蛋疼了。
app
key 寫成一個全局的常量雖然解決了代碼重複的問題,可是體驗上仍是沒有改變。一個 app 裏也有很多的字符串常量,怎麼代表這個字符串是用於持久化的 key 呢?函數
利用 rawValue 類型爲 String 的枚舉做爲 key,經過協議爲指定枚舉增長存取到 UserDefaults 的能力。
首先聲明一個枚舉,建議在UserDefaults的擴展裏寫,固然若是你想要省掉前面一個命名空間也是能夠的:spa
extension UserDefaults {
enum TestData: String,UserDefaultSettable {
case name
}
}複製代碼
注意到這個枚舉須要實現UserDefaultSettable
協議。
接着就能夠在這個枚舉裏調用store(value: )
方法來存儲:code
UserDefaults.TestData.name.store(value: "name")
let storeValue = UserDefaults.TestData.name.storedString複製代碼
這個枚舉TestData.name
能夠理解爲一張銀行卡。拿着這張卡到銀行,說我要存,就夠了。這個枚舉就是一個ID。cdn
這個思路和Swift 3之後的通知中心形式類似。
blog
extension NSNotification {
public struct Name : RawRepresentable, Equatable, Hashable, Comparable {
public init(_ rawValue: String)
public init(rawValue: String)
}
}複製代碼
固然嚴格的說並非一個枚舉,只是和枚舉同樣實現了RawRepresentable
協議。不過我以爲直接聲明一個枚舉在這裏會比實現RawRepresentable
便捷一些。字符串
主要就是UserDefaultSettable
協議的擴展了。get
public protocol UserDefaultSettable {
var uniqueKey: String { get }
}
public extension UserDefaultSettable where Self: RawRepresentable, Self.RawValue == String {
public func store(value: Any?){
UserDefaults.standard.set(value, forKey: uniqueKey)
}
public var storedValue: Any? {
return UserDefaults.standard.value(forKey: uniqueKey)
}
// 爲全部的key加上枚舉名做爲命名空間,避免重複
public var uniqueKey: String {
return "\(Self.self).\(rawValue)"
}
public func store(value: Bool) {
// ......
}
public var storedBool: Bool {
// ......
}
// 還有支持其餘存儲類型的函數,就不全寫了
}複製代碼
主要的實現代碼很簡單,就是爲 RawValue 爲 String 的枚舉添加了 store 和 獲取存儲 value 的方法。string
爲了不直接取枚舉的名字做爲key可能引發的重名,聲明瞭一個計算屬性來生成存儲的 key,規則就是加上枚舉 Type 名做爲前綴。好比上面的例子裏存儲的 key 就是 TestData.name 。
歡迎關注個人微博:@沒故事的卓同窗