对UserDefaults进行子类化

时间:2018-06-13 05:10:23

标签: swift userdefaults

tldr;为什么我们总是使用UserDefaults.standard而不是子类化UserDefaults来制作更符合我们需求的东西呢?

之前有没有人将UserDefaults子类化?或者这被认为是不好的做法?

例如,假设我们创建了UserDefaults的ColorDefaults子类。当应用程序,ColorDefaults对象被实例化,对象加载它自己的所有数据。然后,加载的数据可以通过委托发送到适当的对象,或通过单例普遍提供。

我的运行理论是,UserDefaults仅用于存储相对数量的数据,因此必须使用单例强制执行该想法。

结论:我们使用UserDefaults.standard是因为:

  1. 子类化不满意
  2. 我们应该避免将大量数据保存到UserDefaults
  3. 无论如何,子类化的价值不大?
  4. 几乎所有其他内容。

3 个答案:

答案 0 :(得分:2)

您的ColorDefaults不应该是UserDefaults的子类。它应该是一个普通的结构或类,其计算属性由UserDefaults支持。

以下是使用静态属性的示例,但您可以将其重构为使用单例类。

struct ColorDefaults {
    static var someDefault: String {
        get {
            return UserDefaults.standard.string(forKey: "someKey") ?? "some initial value"
        }
        set {
            UserDefaults.standard.set(newValue, forKey: "someKey")
        }
    }
}

let someVal = ColorDefaults.someDefault // read
ColorDefaults.someDefault = "hello" // write

如果您的一个默认值更复杂并且需要对UserDefaults进行编码/解码,这也很有用。逻辑在这里而不是你的应用程序。

请注意,此类只应用于存储少量偏好,而不是用于存储完整的应用数据。

答案 1 :(得分:0)

用户默认值是文件存储系统。除非你想改变它的一些逻辑,否则在子类化中没有什么意义。但是你可以创建多个套装,比如UserDefaults(suiteName: String)。您希望通过子类化做什么?您可以简单地全局定义let myDefaults = UserDefaults(suiteName: String)并在任何地方使用它。我想你可以使用像

这样的方法
class MyDefaults: UserDefaults {

    func saveName(_ name: String) {
        setValue(name, forKey: "name_key")
    }

}

但是,再次创建一个扩展

可能更有意义
extension UserDefaults {
    func saveName(_ name: String) {
        setValue(name, forKey: "name_key")
    }
}

或者让它更复杂一点:

extension UserDefaults {

    struct User {
        static let defaults = UserDefaults(suiteName: "User")
        static func saveName(_ name: String) {
            defaults.setValue(name, forKey: "name")
        }
    }

    struct General {
        static let defaults = UserDefaults.standard
        static func saveLastOpened(date: Date) {
            defaults.setValue(date, forKey: "last_opened")
        }
    }

}

但所有这些都有一个致命的流程:现在你依赖于在应用程序中使用用户默认值。在某些时候,您可能会发现需要以某种其他形式保存这些数据,例如与iCloud同步的本地JSON文件。我猜UserDefaults.User可能会被修改,但会非常难看。我们想要的不是UserDefaults.User.saveName("My name")而是User.saveName("My name")。从界面的角度来看,我们不关心保存此用户名的位置,如果引入新系统来保存这些数据,我们不希望在界面中进行更改。

换句话说,假设您在应用程序中的100个位置使用UserDefaults.User.saveName,现在想要使用另一个系统来保存用户名。您现在需要在100个地方更改代码才能使用AnotherSystem.User.saveName,而如果您只是使用User.saveName,则界面仍然有效。

所以底线是(广泛地)修改,扩展或子类化UserDefaults没有任何意义,因为它最好创建一个包装UserDefaults的系统,以后可能会更改为任何其他系统。

答案 2 :(得分:-1)

好像你正在寻找类似的东西

class ColorDefaults : NSObject
{
    /// Save Data
    class func saveDataInDefaultForKey(_ key: String, _ data: Any){
        UserDefaults.standard.set(data, forKey: key)
    }

    /// Retrieve data
    class func retrieveDataFromDefaultsWithKey(_ key: String) -> Any {
        return UserDefaults.standard.value(forKey: key) as Any
    }
}

保存并获取数据:

/// Save Data
ColorDefaults.saveDataInDefaultForKey("myArray", myArray)
ColorDefaults.saveDataInDefaultForKey("myString", myString)

/// Get Data
if let valueString = ColorDefaults.retrieveDataFromDefaultsWithKey("myString") as? String {
        print("Saved Value String: \(valueString)")
 }
 else {
        print("Error retrieving myString")
 }

 if let valueArray = ColorDefaults.retrieveDataFromDefaultsWithKey("myArray") as? [String] {
        print("Saved Value Array: \(valueArray)")
 }
 else{
        print("Error retrieving myArray")
 }

输出:

enter image description here