美文网首页iOS开发技术ios专题买不来的iOS实用技巧
UserDefault 数据存储和读取简易封装

UserDefault 数据存储和读取简易封装

作者: NinthDay | 来源:发表于2017-02-11 22:02 被阅读1572次

    方式一

    代码如下:

    protocol UserDefaultNameSpace { }
    
    extension UserDefaultNameSpace {
        static func namespace<T>(_ key:T) -> String where T :RawRepresentable {
            return "\(Self.self).\(key.rawValue) "
        }
    }
    
    protocol UserDefaultSettable : UserDefaultNameSpace {
        associatedtype UserDefaultKey : RawRepresentable
    }
    
    extension UserDefaultSettable where UserDefaultKey.RawValue == String {}
    
    extension UserDefaultSettable {
        
        /// 关于 Int 类型存储和读取
        static func set(value:Int, forKey key:UserDefaultKey){
            let key = namespace(key)
            UserDefaults.standard.set(value, forKey: key)
        }
        
        static func integer(forKey key:UserDefaultKey) -> Int {
            let key = namespace(key)
            return UserDefaults.standard.integer(forKey: key)
        }
        
        /// 关于 String 类型存储和读取
        static func set(value:Any?, forKey key:UserDefaultKey){
            let key = namespace(key)
            UserDefaults.standard.set(value, forKey: key)
        }
        
        static func string(forKey key:UserDefaultKey) -> String? {
            let key = namespace(key)
            return UserDefaults.standard.string(forKey: key)
        }
    }
    
    extension UserDefaults {
        
        /*! 关于账号的信息 Key 都放在这里 */
        struct Account: UserDefaultSettable {
            enum UserDefaultKey : String {
                case name
                case age
                case birth
            }
        }
        
        /*! 关于登陆情况 Key 都放在这里 */
        struct LoginStatus: UserDefaultSettable {
            enum UserDefaultKey:String {
                case lastLoginTime
                case sessionTime
            }
        }
    }
    
    /// 使用方式
    UserDefaults.Account.set(value: 20, forKey: .age)
    UserDefaults.Account.set(value: "pmst", forKey: .name)
    UserDefaults.Account.set(value: "20170214", forKey: .birth)
    

    方式二

    卓同学的另一种实现思路:

    public protocol UserDefaultSettable {
        var uniqueKey: String { get }
    }
    
    public extension UserDefaultSettable where Self: RawRepresentable, Self.RawValue == String {
        
        public func set(value: Any?){
            UserDefaults.standard.set(value, forKey: uniqueKey)
        }
        
        public var value: Any? {
            return UserDefaults.standard.value(forKey: uniqueKey)
        }
        
        public var stringValue: String? {
            return value as? String
        }
        
        public func set(url: URL?) {
            UserDefaults.standard.set(url, forKey: uniqueKey)
        }
        
        public var urlValue: URL? {
            return UserDefaults.standard.url(forKey: uniqueKey)
        }
        
        public var uniqueKey: String {
            return "\(Self.self).\(rawValue)"
        }
        
        /// removed object from standard userdefaults
        public func removed() {
            UserDefaults.standard.removeObject(forKey: uniqueKey)
        }
        
    }
    
    extension UserDefaults {
        enum TestData: String,UserDefaultSettable {
            case name
            case url
        }
    }
    
    let value = "testValue"
    if let _ = UserDefaults.TestData.name.stringValue {
        assertionFailure("should be nil")
    }
    UserDefaults.TestData.name.set(value: value)
    
    UserDefaults.TestData.name.stringValue
    

    当然这里我们还商讨了下命名规则,觉得setstringValue不是很恰到,之后会改成 store 动词。

    方式三:

    智多芯的博客中又提到了一种方式,我觉得也比较好,贴下代码:

    final class PreferenceKey<T>: PreferenceKeys { }
    class PreferenceKeys: RawRepresentable, Hashable {
        let rawValue: String
        
        required init!(rawValue: String) {
            self.rawValue = rawValue
        }
        
        convenience init(_ key: String) {
            self.init(rawValue: key)
        }
        
        var hashValue: Int {
            return rawValue.hashValue
        }
    }
    extension PreferenceKeys {
        static let launchAtLogin = PreferenceKey<Bool>("LaunchAtLogin")
        static let launchCount = PreferenceKey<Int>("LaunchCount")
        static let userInfo = PreferenceKey<UserInfo>("UserInfo")
    }
    

    接着定义一个专门负责存储的管理类

    final class PreferenceManager {
        static let shared = PreferenceManager()
        let defaults = UserDefaults.standard
        
        private init() {
            registerDefaultPreferences()
        }
        
        private func registerDefaultPreferences() {
            // Convert dictionary of type [PreferenceKey: Any] to [String: Any].
            let defaultValues: [String: Any] = defaultPreferences.reduce([:]) {
                var dictionary = $0
                dictionary[$1.key.rawValue] = $1.value
                return dictionary
            }
            defaults.register(defaults: defaultValues)
        }
    }
    let defaultPreferences: [PreferenceKeys: Any] = [
        .launchAtLogin: false,
        .launchCount: 0,
        .userInfo: NSKeyedArchiver.archivedData(withRootObject: UserInfo(id: 0, name: "")),
    ]
    

    extension 补充下:

    extension PreferenceManager {
        subscript(key: PreferenceKey<Any>) -> Any? {
            get { return defaults.object(forKey: key.rawValue) }
            set { defaults.set(newValue, forKey: key.rawValue) }
        }
        
        subscript(key: PreferenceKey<URL>) -> URL? {
            get { return defaults.url(forKey: key.rawValue) }
            set { defaults.set(newValue, forKey: key.rawValue) }
        }
        
        subscript(key: PreferenceKey<[Any]>) -> [Any]? {
            get { return defaults.array(forKey: key.rawValue) }
            set { defaults.set(newValue, forKey: key.rawValue) }
        }
        
        subscript(key: PreferenceKey<[String: Any]>) -> [String: Any]? {
            get { return defaults.dictionary(forKey: key.rawValue) }
            set { defaults.set(newValue, forKey: key.rawValue) }
        }
        
        subscript(key: PreferenceKey<String>) -> String? {
            get { return defaults.string(forKey: key.rawValue) }
            set { defaults.set(newValue, forKey: key.rawValue) }
        }
        
        subscript(key: PreferenceKey<[String]>) -> [String]? {
            get { return defaults.stringArray(forKey: key.rawValue) }
            set { defaults.set(newValue, forKey: key.rawValue) }
        }
        
        subscript(key: PreferenceKey<Data>) -> Data? {
            get { return defaults.data(forKey: key.rawValue) }
            set { defaults.set(newValue, forKey: key.rawValue) }
        }
        
        subscript(key: PreferenceKey<Bool>) -> Bool {
            get { return defaults.bool(forKey: key.rawValue) }
            set { defaults.set(newValue, forKey: key.rawValue) }
        }
        
        subscript(key: PreferenceKey<Int>) -> Int {
            get { return defaults.integer(forKey: key.rawValue) }
            set { defaults.set(newValue, forKey: key.rawValue) }
        }
        
        subscript(key: PreferenceKey<Float>) -> Float {
            get { return defaults.float(forKey: key.rawValue) }
            set { defaults.set(newValue, forKey: key.rawValue) }
        }
        
        subscript(key: PreferenceKey<Double>) -> Double {
            get { return defaults.double(forKey: key.rawValue) }
            set { defaults.set(newValue, forKey: key.rawValue) }
        }
        
        subscript(key: PreferenceKey<UserInfo>) -> UserInfo? {
            get {
                var object: UserInfo?
                if let data = defaults.data(forKey: key.rawValue) {
                    object = NSKeyedUnarchiver.unarchiveObject(with: data) as? UserInfo
                }
                return object
            }
            set {
                if let object = newValue {
                    let data = NSKeyedArchiver.archivedData(withRootObject: object)
                    defaults.set(data, forKey: key.rawValue)
                }
            }
        }
    }
    

    使用方式如下:

    let Preferences = PreferenceManager.shared
    func demo() {
        let userDefaults = UserDefaults.standard
        
        // Test data.
        var launchAtLogin = true
        var launchCount = 10
        var userInfo: UserInfo? = UserInfo(id: 123, name: "Fox")
        
        // Write preference.
        Preferences[.launchAtLogin] = launchAtLogin
        Preferences[.launchCount] = launchCount
        Preferences[.userInfo] = userInfo
        
        // Read preference.
        launchAtLogin = Preferences[.launchAtLogin]
        launchCount = Preferences[.launchCount]
        userInfo = Preferences[.userInfo]
        
        // Check preferences.
        for (key, value) in userDefaults.dictionaryRepresentation() {
            print("\(key): \(value)")
        }
    }
    

    新浪微博:Ninth_Day

    相关文章

      网友评论

      • 木_木27:请问一下,在OC与swift混编的情况下,适合用这种方法吗?谢谢
      • valentizx:我天 最后一个太好用了 准备封装一个清楚的再
        NinthDay:@valentizx :smile:
      • figure_ai:大神,你的博客为什么会出现在swift-GG:scream:
        NinthDay:@figure_ai :beers:
        figure_ai:@NinthDay 膜拜:+1: 感谢有你们的存在
        NinthDay:@figure_ai 我是SwiftGG翻译组成员 那边叫pmst
      • 没故事的卓同学:写的非常好。我偷走了。

      本文标题:UserDefault 数据存储和读取简易封装

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