人在江湖飄,總免不了要存一些值到UserDefaults。
UserDefaults.standard.set("@沒故事的卓同學(xué)", forKey: "Author")
let author = UserDefaults.standard.value(forKey: "Author")
有存就有取征唬,還可能有很多地方會取這個值菩咨。這樣的話每次寫這個 key 就有點蛋疼了吠式。
key 寫成一個全局的常量雖然解決了代碼重復(fù)的問題陡厘,但是體驗上還是沒有改變。一個 app 里也有不少的字符串常量特占,怎么表明這個字符串是用于持久化的 key 呢糙置?
解決方案
利用 rawValue 類型為 String 的枚舉作為 key,通過協(xié)議為指定枚舉增加存取到 UserDefaults 的能力是目。
首先聲明一個枚舉谤饭,建議在UserDefaults的擴(kuò)展里寫,當(dāng)然如果你想要省掉前面一個命名空間也是可以的:
extension UserDefaults {
enum TestData: String,UserDefaultSettable {
case name
}
}
注意到這個枚舉需要實現(xiàn)<code>UserDefaultSettable</code>協(xié)議懊纳。
接著就可以在這個枚舉里調(diào)用<code>store(value: )</code>方法來存儲:
UserDefaults.TestData.name.store(value: "name")
let storeValue = UserDefaults.TestData.name.storedString
這個枚舉<code>TestData.name</code>可以理解為一張銀行卡揉抵。拿著這張卡到銀行,說我要存嗤疯,就夠了冤今。這個枚舉就是一個ID。
這個思路和Swift 3以后的通知中心形式相似茂缚。
Notification.Name 也是一個 rawValue 為字符串的枚舉戏罢。
extension NSNotification {
public struct Name : RawRepresentable, Equatable, Hashable, Comparable {
public init(_ rawValue: String)
public init(rawValue: String)
}
}
當(dāng)然嚴(yán)格的說并不是一個枚舉,只是和枚舉一樣實現(xiàn)了<code>RawRepresentable</code>協(xié)議脚囊。不過我覺得直接聲明一個枚舉在這里會比實現(xiàn)<code>RawRepresentable</code>便捷一些龟糕。
實現(xiàn)
主要就是<code>UserDefaultSettable</code>協(xié)議的擴(kuò)展了。
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加上枚舉名作為命名空間悔耘,避免重復(fù)
public var uniqueKey: String {
return "\(Self.self).\(rawValue)"
}
public func store(value: Bool) {
// ......
}
public var storedBool: Bool {
// ......
}
// 還有支持其他存儲類型的函數(shù)翩蘸,就不全寫了
}
主要的實現(xiàn)代碼很簡單,就是為 RawValue 為 String 的枚舉添加了 store 和 獲取存儲 value 的方法淮逊。
為了避免直接取枚舉的名字作為key可能引起的重名催首,聲明了一個計算屬性來生成存儲的 key,規(guī)則就是加上枚舉 Type 名作為前綴泄鹏。比如上面的例子里存儲的 key 就是 TestData.name 郎任。
歡迎關(guān)注我的微博:@沒故事的卓同學(xué)
參考鏈接:
Swift: UserDefaults Protocol
UserDefault 數(shù)據(jù)存儲和讀取簡易封裝