【发布时间】:2021-04-08 17:50:04
【问题描述】:
我正在设置我的 Settings 类,它从 UserDefaults 获取/设置值。我希望尽可能多的代码是通用的,以尽量减少引入新设置时所涉及的工作量(我有很多,我希望将来还会有更多),从而减少任何人为错误/错误的可能性.
我遇到this answer 为 UserDefaults 创建一个包装器:
struct UserDefaultsManager {
static var userDefaults: UserDefaults = .standard
static func set<T>(_ value: T, forKey: String) where T: Encodable {
if let encoded = try? JSONEncoder().encode(value) {
userDefaults.set(encoded, forKey: forKey)
}
}
static func get<T>(forKey: String) -> T? where T: Decodable {
guard let data = userDefaults.value(forKey: forKey) as? Data,
let decodedData = try? JSONDecoder().decode(T.self, from: data)
else { return nil }
return decodedData
}
}
我创建了一个枚举来存储所有设置键:
enum SettingKeys: String {
case TimeFormat = "TimeFormat"
// and many more
}
每个设置都有自己的枚举:
enum TimeFormat: String, Codable {
case ampm = "12"
case mili = "24"
}
在这个简化的 Settings 类示例中,您可以看到当它被实例化时,我初始化了每个定义的设置的值。我检查是否在 UserDefaults 中找到了它的设置键:如果是,我使用找到的值,否则我将其设置为默认值并第一次将其保存到 UserDefaults。
class Settings {
var timeFormat: TimeFormat!
init() {
self.initTimeFormat()
}
func initTimeFormat() {
guard let format: TimeFormat = UserDefaultsManager.get(forKey: SettingKeys.TimeFormat.rawValue) else {
self.setTimeFormat(to: .ampm)
return
}
self.timeFormat = format
}
func setTimeFormat(to format: TimeFormat) {
UserDefaultsManager.set(format, forKey: SettingKeys.TimeFormat.rawValue)
self.timeFormat = format
}
}
这工作正常,而且非常简单。但是,提前考虑,为这个应用程序中的每个设置(以及我将来希望做的所有其他设置)复制这将是乏味的(因此容易出错)。有没有办法将init<name of setting>() 和set<name of setting>() 通用化,我通过它传递一个设置键(仅此而已),然后它处理其他所有事情?
我已经确定每个设置都有这些共享元素:
- 设置键(例如我的示例中的 SettingsKey.TimeFormat)
- 唯一类型(可以是 AnyObject、String、Int、Bool 等,例如我的示例中的枚举 TimeFormat)
- 唯一属性(例如我的示例中的 timeFormat)
- 默认值(例如我的示例中的 TimeFormat.ampm)
一如既往的感谢!
更新:
这可能会或可能不会有所不同,但考虑到所有设置都有默认值,我意识到它们不需要是非可选的,但可以在初始化时设置默认值。
即改变:
var timeFormat: TimeFormat!
func initTimeFormat() {
guard let format: TimeFormat = UserDefaultsManager.get(forKey: SettingKeys.TimeFormat.rawValue) else {
self.setTimeFormat(to: .ampm)
return
}
self.timeFormat = format
}
收件人:
var timeFormat: TimeFormat = .ampm
func initTimeFormat() {
guard let format: TimeFormat = UserDefaultsManager.get(forKey: SettingKeys.TimeFormat.rawValue) else {
UserDefaultsManager.set(self.timeFormat, forKey: SettingKeys.TimeFormat.rawValue)
return
}
self.timeFormat = format
}
setTimeFormat() 函数的值在用户在应用内更改时仍然需要。
【问题讨论】:
标签: ios swift settings generic-programming userdefaults