I am trying to come up with a way to access UserDefaults using properties. However, I am stuck because I can't figure out how to make the properties dynamic, so to speak.
This is the generic idea, that API that I want:
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)")
But that (of course) doesn't work, since the type is DefaultsKey<String>
, not String
. So I have to add a value property to the DefaultsKey
implementation just to add the getter and the setter, like this:
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()
}
}
}
and then use it like this:
let props = AppUserDefaults()
props.username.value = "bla"
print("username: \(props.username.value)")
But I find that rather ugly. I also tried a subscript method, but then you're still required to add []
instead of .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[])")
Basically what I want is that I can define the getter and the setter directly on DefaultsKey
instead of having to go through that value
property. Is this simply not possible with Swift? Is there another way to get the behaviour that I want, where properties defined on AppUserDefaults
are "dynamic" and go through a getter and setter, without having to define it on the property declaration inside of AppUserDefaults
?
I hope I am using the correct terms here and made the question clear for everyone.
Getters and setters are essential in any language. Here, in Swift, they are applied to computed properties that do not have access to their own storage, so need to be derived from other properties.
Classes within Swift are often seen as a blueprint for creating objects. With the ability to store values by defining properties and adding functionality through creating methods, classes and structs' shared features can often be used interchangeably in Swift.
Getters and setters are used to protect your data, particularly when creating classes. For each instance variable, a getter method returns its value while a setter method sets or updates its value. Given this, getters and setters are also known as accessors and mutators, respectively.
The only thing I can think of is this:
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()
}
}
}
class AppUserDefaults {
private var _username = DefaultsKey<String>("username", defaultValue: "Unknown")
var username: String {
set {
_username.value = newValue
},
get {
return _username.value
}
}
}
let props = AppUserDefaults()
props.username = "bla"
print("username: \(props.username)")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With