美文网首页Swift随笔
三步走:使用Property Wrapper优化UserDefa

三步走:使用Property Wrapper优化UserDefa

作者: CoderXLL | 来源:发表于2020-11-30 11:02 被阅读0次

    本次优化受到喵神使用 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中增加缓存值的代码简单便捷
    • 调用时,直接操作对应的缓存值

    相关文章

      网友评论

        本文标题:三步走:使用Property Wrapper优化UserDefa

        本文链接:https://www.haomeiwen.com/subject/fszxwktx.html