正文
開發(fā)過iOS的人,一定使用過UserDefaults來存取數(shù)據(jù)。UserDefaults使用起來很簡單,我們就以存取用戶名和郵箱為例,來探討下UserDefaults的具體使用。
存儲代碼
let username = "DerekCoder"
let email = "derekcoder@gmail.com"
let defaults = UserDefaults.standard
defaults.set(username, forKey: "username")
defaults.set(email, forKey: "email")
讀取代碼
let defaults = UserDefaults.standard
let username = defaults.string(forKey: "username") // 類型: String?
let email = defaults.string(forKey: "email") // 類型: String?
雖然實現(xiàn)很簡單,但是上面代碼有個很明顯的問題。"username"和"email"這兩個常量我們不應該每次用到都敲一遍,這樣很容易敲錯或者忘記具體怎么拼寫,我們應該充分利用IDE自動補全的功能。
OK,我們對上面代碼進行改進
let username = "DerekCoder"
let email = "derekcoder@gmail.com"
let KEY_FOR_USERNAME = "username"
let KEY_FOR_EMAIL = "email"
let defaults = UserDefaults.standard
defaults.set(username, forKey: KEY_FOR_USERNAME)
defaults.set(email, forKey: KEY_FOR_EMAIL)
let defaults = UserDefaults.standard
let username = defaults.string(forKey: KEY_FOR_USERNAME) // 類型: String?
let email = defaults.string(forKey: KEY_FOR_EMAIL) // 類型: String?
這時候我們就解決了敲錯Key的名字的問題,但是還是有一個問題,就是如果我們不記得定義的常量名字怎么辦,當然這時候我們可以去定義的常量的文件查看,這樣的話就會打斷你當前的進程,影響效率,也影響心情。那有沒有一種方法可以讓IDE自動提示你當前定義的所有的UserDefault Keys,然后我們只要選擇就可以了。
我的解決方案如下:
- 添加一個新的類型
UserDefaults.Name
extension UserDefaults {
public struct Name: RawRepresentable, Equatable {
public var rawValue: String
public init(rawValue: String) {
self.rawValue = rawValue
}
public init(_ rawValue: String) {
self.rawValue = rawValue
}
}
}
- 擴展UserDefaults.Name類型,讓它支持字符串直接賦值
extension UserDefaults.Name: ExpressibleByStringLiteral {
public typealias UnicodeScalarLiteralType = String
public typealias ExtendedGraphemeClusterLiteralType = String
public init(stringLiteral value: String) {
self.rawValue = value
}
public init(unicodeScalarLiteral value: String) {
self.init(stringLiteral: value)
}
public init(extendedGraphemeClusterLiteral value: String) {
self.init(stringLiteral: value)
}
}
- 擴展UserDefaults,添加新的方法來實現(xiàn)賦值和讀取數(shù)據(jù)
extension UserDefaults {
public func object(forName name: UserDefaults.Name) -> Any? {
return object(forKey: name.rawValue)
}
public func set(_ value: Any?, forName name: UserDefaults.Name) {
set(value, forKey: name.rawValue)
}
public func string(forName name: UserDefaults.Name) -> String? {
return string(forKey: name.rawValue)
}
// 此處省略了一些的方法
...
}
- 定義你的Key常量
extension UserDefaults.Name {
static let username: UserDefaults.Name = "username"
static let email: UserDefaults.Name = "email"
}
- 實現(xiàn)你的賦值和讀取
let defaults = UserDefaults.standard
defaults.set(username, forName: .username)
defaults.set(email, forName: .email)
let username = defaults.string(forName: .username) // 類型: String?
let email = defaults.string(forName: .email) // 類型: String?
最后一步賦值和讀取時,當你需要用到Key常量時,你只需要先敲一個點,Xcode就會把所有的UserDefaults的Key常量展示出來,你選擇你需要的key即可。你再也不用害怕敲錯或者忘記定義的常量名字具體是什么了。

Screen Shot 2017-09-19 at 4.00.49 PM.png
我們再做一個擴展,讓UserDefaults支持,如果對應的Key的值不存在,返回一個defaultValue。
extension UserDefaults {
public func string(forName name: UserDefaults.Name, defaultValue: String) -> String {
return string(forKey: name.rawValue) ?? defaultValue
}
}
let defaults = UserDefaults.standard
let username = defaults.string(forName: .username, defaultValue: "Unknown") // 類型: String
總結
- 對于
UserDefaults的擴展,為了強調(diào)重點,我省略了一些方法。查看全部代碼,請參考SwiftDevHints
聯(lián)系方式
備注
我們在軟件開發(fā)的過程中,為了提高效率,其中很重要的一環(huán)就是把反復使用到的功能或模塊封裝起來。因此我在GitHub上開源了一個小工具集 - SwiftDevHints,來總結自己在實際項目開發(fā)過程中封裝的一些小功能。
剛剛介紹的只是其中一個小功能,想看看其它更多功能,請直接點擊SwiftDevHints。如果您覺得對您有所幫助,請給一個star吧。