I have seen people using UserDefaults.setValue()
occasionally. Below is an example I find here and it works fine.
@propertyWrapper struct AppSetting<Value> {
let key: String
let defaultValue: Value
var container: UserDefaults = .standard
var wrappedValue: Value {
get { container.value(forKey: key) as? Value ?? defaultValue}
set { container.setValue(newValue, forKey: key) }
}
}
From what I can find in Apple's docs, setValue()
is an API of NSObject
for its KVO feature, and UserDefaults
class inherits from NSObject
. However, it's not clear what the API exactly does when it's called on UserDefaults
. From the above example, I can guess it (it seems that UserDefaults
overrides this method). But otherwise I'd think it sets a property of a UserDefaults
obect, which is meaningless. So I wonder how people find this usage? Is it documented anywhere?
UPDATE: I probably didn't describe my question clearly. I knew what KVO is. What I'm confused is how KVO relates to UserDefaults. From my understanding, the key in KVO and that in UserDefaults have completely different meaning. Key in KVO is property of an object. Key in UserDefaults is the key in key/value data store. So my questions is: how the API for KVO can be used to update a key/value pair in data store? Could it be that UserDefaults
instance creates properties for each key in the data store? But that is an implementation detail and it's not obvious to me.
UPDATE 2: as @rob-mayoff and @HangarRash pointed out, setValue()
is an API for KVC, not KVO. That said, I think the original question is still valid.
CodePudding user response:
UserDefaults
is documented to support key-value observing (KVO), so that you can use KVO to be notified when specific settings are changed:
You can use key-value observing to be notified of any updates to a particular default value.
KVO-compliance generally implies support for key-value coding (KVC):
In order to be considered KVO-compliant for a specific property, a class must ensure the following:
- The class must be key-value coding compliant for the property, as specified in Ensuring KVC Compliance.
The value(forKey:)
and setValue(forKey:)
methods are part of KVC.
However, I would recommend sticking to the UserDefaults
-specific methods as they might be implemented more efficiently.
CodePudding user response:
I'm assuming you are actually asking about KVC (key-value coding) and not KVO (key-value observing) since you are asking about KVC methods setValue:forKey:
/valueForKey:
and not about KVO methods such as addObserver...
and observeValueForKeyPath:...
.
You state: "Key in KVO is property of an object."
Not necessarily. If you go through the Key-Value Coding Programming Guide you will find the following basic summary (emphasis mine):
- Access object properties.
- Manipulate collection properties.
- Invoke collection operators on collection objects.
- Access non-object properties.
- Access properties by key path.
Look at NSMutableDictionary
for an example of using KVC with a collection. UserDefaults
(NSUserDefaults
) is basically a wrapper around a dictionary. So the same KVC rules that apply to a dictionary apply to user defaults.
More details on this can be found at Accessing Collection Properties and Accessor Search Patterns.
Note that with simple keys, setValue:forKey:
/valueForKey:
are the same as setObject:forKey:
/objectForKey:
. And the various UserDefaults
APIs are just type safe wrappers around setObject:forKey:
/objectForKey:
.
In the end, unless you have specific needs for KVC, use the supplied API of UserDefaults
and avoid using setValueForKey:/valueForKey:
.