三步走:使用Property Wrapper优化UserDefa
2020-11-30 本文已影响0人
CoderXLL
本次优化受到喵神使用 Property Wrapper 为 Codable 解码设定默认值的启发,不断地思考发现问题,不断地在现有基础上优化解决问题。特此感谢
一、成长期
1.调用方式
private let isAgreePrivacyKey = "isAgreePrivacy"
//1. 存缓存
UserDefaults(suiteName: "appUserSuite")!setValue(true, forKey: isAgreePrivacyKey)
//2. 取缓存
UserDefaults(suiteName: "appUserSuite")!.bool(forKey: isAgreePrivacyKey)
2.缺点
- 存取的代码过长,不方便调用。且会产生很多冗余代码
- 每次存取都需要进行文件的IO操作,耗费性能
二、完全体
1.内部实现
final public class XLLDefaultsBox<T> {
public var value: T {
didSet {
setterAction(value)
}
}
public typealias SetterAction = (T) -> Void
var setterAction: SetterAction
public init(_ v: T, setterAction action: @escaping SetterAction) {
value = v
setterAction = action
}
}
private let isAgreePrivacyKey = "isAgreePrivacy"
final public class XLLAppDefaults {
static let appUser = UserDefaults(suiteName: "appUserSuite")
public static var isAgreePrivacy: XLLDefaultsBox<Bool?> = {
let isAgreePrivacy = appUser.bool(forKey: isAgreePrivacyKey)
return XLLDefaultsBox<Bool?>(isAgreePrivacy) { isAgreePrivacy in
appUser.set(isAgreePrivacy, forKey: isAgreePrivacyKey)
}
}()
}
2.调用方式
//1. 存缓存
XLLAppDefaults.isAgreePrivacy.value = true
//2. 取缓存
XLLAppDefaults.isAgreePrivacy.value
3. 优点
- App运行期间,针对每个缓存值只有第一次进行了文件O操作,后面读取
XLLDefaultsBox
中的value值即可 - 调用时的代码大大缩减,并且容易记忆
4. 缺点
-
XLLDefaultsBox
类的设计会让不熟悉代码的同志们感到困惑 -
XLLAppDefaults
中每增加一个缓存的那串代码过长很不方便,对于使用者不太友好 - 调用时,需要直接获取与设置的是缓存值的value,这样会让人很疑惑且容易漏写
三、究极体
1. 内部实现
extension UserDefaults {
static var appUser: UserDefaults = UserDefaults(suiteName: "appUserSuite")!
}
@propertyWrapper
struct XLLAppDefaultsWrapper<T> {
var key: String?
var value: T
var wrappedValue: T {
get { value }
set {
value = newValue
if let key = key {
UserDefaults.appUser.setValue(newValue, forKey: key)
}
}
}
public init(_ initialValue: T, key: String) {
value = initialValue
self.key = key
}
}
private let isAgreePrivacyKey = "isAgreePrivacy"
public class XLLAppDefaults {
public static let shared = XLLAppDefaults()
//注意,这里若非跨模块调用,权限关键词public可去除
@XLLAppDefaultsWrapper<Bool>(UserDefaults.appUser.bool(forKey: isAgreePrivacyKey), key: isAgreePrivacyKey)
public var isAgreePrivacy
}
2.调用方式
//存缓存
XLLAppDefaults.shared.isAgreePrivacy = false
//取缓存
XLLAppDefaults.shared.isAgreePrivacy
3.优点
- 延续了第二种方式减少了IO操作的优点
- 使用
@propertyWrapper
的思想,代码很优雅 -
XLLAppDefaults
中增加缓存值的代码简单便捷 - 调用时,直接操作对应的缓存值