×

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

96
NinthDay
2017.02.11 22:02* 字数 126

方式一

代码如下:

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

Web note ad 1