开发中经常会用到UserDefault来存储零碎的数据, 用普通的写法比较低效.
1
let uid = UserDefaults.standard.value(forKey: "userdefault.key.uid") as? Int
可以利用Swift的extension
来给Int类型添加便捷的函数:
1
2
3
4
5
6
7
extension Int {
static func valueFromUserDefault(forKey key: String) -> Int? {
return UserDefaults.standard.value(forKey: key) as? Int
}
}
let uid = Int.valueFromUserDefault(forKey: "userdefault.key.uid")
而实际上, UserDefault存储的数据类型还有好几种, 而实现代码其实都是大同小异, 要每一个都这样添加函数就太麻烦了. 有一种更高效的方式给各种类型添加这个函数, 而且也方便统一修改. 就是用泛型和Protocol:
1
2
3
4
5
6
7
8
9
10
11
public protocol UserDefaultable {
associatedtype E
static func objectUserDefaults(forKey key: String) -> E?
}
extension UserDefaultable {
public static func valueFromUserDefaults(forKey key: String) -> E? {
return UserDefaults.standard.value(forKey: key) as? E
}
}
这样只要声明了遵守UserDefaultable的类型都可以使用valueFromUserDefaults
静态函数, 很自然, 这个associatedtype E
就是绑定这个类型本身.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
extension Bool: UserDefaultable {
public typealias E = Bool
}
extension Int: UserDefaultable {
public typealias E = Int
}
extension Int32: UserDefaultable {
public typealias E = Int32
}
extension Int64: UserDefaultable {
public typealias E = Int64
}
extension String: UserDefaultable {
public typealias E = String
}
extension Double: UserDefaultable {
public typealias E = Double
}
extension Data: UserDefaultable {
public typealias E = Data
}
extension Array: UserDefaultable {
public typealias E = Array
}