Я пытаюсь найти способ доступа к UserDefaults с использованием свойств. Тем не менее, я застрял, потому что не могу понять, как сделать свойства динамическими, так сказать.
Это общая идея, которую я хочу получить API:
class AppUserDefaults {
var username = DefaultsKey<String>("username", defaultValue: "Unknown")
var age = DefaultsKey<Int?>("age", defaultValue: nil)
}
let props = AppUserDefaults()
props.username = "bla"
print("username: \(props.username)")
Но это (конечно) не работает, так как тип DefaultsKey<String>
, а не String
. Поэтому я должен добавить свойство value в реализацию DefaultsKey
чтобы добавить getter и setter, например:
struct DefaultsKey<ValueType> {
private let key: String
private let defaultValue: ValueType
public init(_ key: String, defaultValue: ValueType) {
self.key = key
self.defaultValue = defaultValue
}
var value: ValueType {
get {
let value = UserDefaults.standard.object(forKey: key)
return value as? ValueType ?? defaultValue
}
set {
UserDefaults.standard.setValue(newValue, forKey: key)
UserDefaults.standard.synchronize()
}
}
}
и затем используйте его следующим образом:
let props = AppUserDefaults()
props.username.value = "bla"
print("username: \(props.username.value)")
Но я нахожу это довольно уродливым. Я также попробовал подстрочный метод, но тогда вам все равно нужно добавить []
вместо .value
:
struct DefaultsKey<ValueType> {
...
subscript() -> ValueType {
get {
let value = UserDefaults.standard.object(forKey: key)
return value as? ValueType ?? defaultValue
}
set {
UserDefaults.standard.setValue(newValue, forKey: key)
UserDefaults.standard.synchronize()
}
}
}
let props = AppUserDefaults()
props.username[] = "bla"
print("username: \(props.username[])")
В принципе, я хочу, чтобы я мог определить getter и setter непосредственно на DefaultsKey
вместо того, чтобы пройти через это свойство value
. Это просто невозможно с Swift? Есть ли другой способ получить поведение, которое я хочу, где свойства, определенные в AppUserDefaults
являются "динамическими" и проходят через getter и setter, без необходимости определять его в объявлении свойства внутри AppUserDefaults
?
Надеюсь, я использую здесь правильные условия и поставил вопрос каждому.