Setting default values for NSUserDefaults
Table of Contents
UserDefaults (NSUserDefaults
) is a go-to database for saving users' preferences over application behavior, e.g., font size, sound disable/enable. So, most of the time, you want each of them to have a default value.
Basic approach
Let say your app allows users to enable/disable sound and vibration. If you want to have both of them turn on by default, you might do something like this.
let userDefaults = UserDefaults.standard
if userDefaults.value(forKey: "enabledSound") == nil { // 1
userDefaults.set(true, forKey: "enabledSound") // 2
}
// 3
if userDefaults.value(forKey: "enabledVibration") == nil {
userDefaults.set(true, forKey: "enabledVibration")
}
<1> First, you get a value from your preference key. Notice that we use .value(forKey:)
not bool(forKey:)
because bool(forKey:)
will return false
if the value is nil
, so you can differentiate between nil
and false
.
<2> If the value is nil
, we set a default value of true
.
<3> The same applies to enabledVibration
.
This might be good enough for your case, but it quite verbose. You have to repeat this for every option that you have.
You can easily support sarunw.com by checking out this sponsor.
AI Grammar: Correct grammar, spell check, check punctuation, and parphrase.
The right approach with register(defaults:)
What you might not aware of is you don't even have to come up with anything fancy. UserDefaults has a register(defaults:)
method for a situation like this.
To use register(defaults:)
, you need to specify a dictionary of preference keys and their default value. In the following example, we set both enabledSound
and enabledVibration
a default value of true
.
let userDefaults = UserDefaults.standard
userDefaults.register(
defaults: [
"enabledSound": true,
"enabledVibration": true
]
)
userDefaults.bool(forKey: "enabledSound") // true
The code is a lot cleaner and cleaner. That's all you need to do to set a default value for your UserDefaults. There are some behaviors of register(defaults:)
that I want to point out for you.
The value is only set if the key is nil
If a user sets any preference key, register(defaults:)
won't override that key. This is quite obvious behavior for a method that works to set a default value, but I want to assure you that you can safely call register(defaults:)
from anywhere and as many as you want.
let userDefaults = UserDefaults.standard
userDefaults.set(false, forKey: "enabledSound") // 1
userDefaults.register(
defaults: [
"enabledSound": true, // 2
"enabledVibration": true
]
)
userDefaults.bool(forKey: "enabledSound") // false
<1> We explicit set enabledSound
to false
.
<2> The value true
that we set with register(defaults:)
won't take effect on this, and the value remains false
.
The default values are not persist
The following statement is coming from the Apple documentation of UserDefaults.
The contents of the registration domain are not written to disk; you need to call this method each time your application starts.
So, if you have this code in your application(_:didFinishLaunchingWithOptions:)
.
let userDefaults = UserDefaults.standard
print(userDefaults.integer(forKey: "counter")) // print 0
userDefaults.register(
defaults: [
"counter": 5
]
)
print(userDefaults.integer(forKey: "counter")) // print 5
On the first run, it will print out 0
then 5
. On the second run, you might expect it to print 5
and 5
, but that's not the case. It still prints out 0
and 5
.
The value that is set through register(defaults:)
method isn't actually written to disk until you explicitly set it with set(_:forKey:).
. That means you need to call register(defaults:)
each time your application starts to get the right behavior.
Read the value from plist
Since plist is a serialization of a dictionary, you can pack your default values into a plist file and call register(defaults:)
with the contents from that file. You can modify your default values without touching your codebase this way.
To do that:
- Create a plist file with associated key and default value.
private func readPropertyList() -> [String: Any]? {
guard let plistPath = Bundle.main.path(forResource: "DefaultValues", ofType: "plist"),
let plistData = FileManager.default.contents(atPath: plistPath) else {
return nil
}
return try? PropertyListSerialization.propertyList(from: plistData, format: nil) as? [String: Any]
}
- Register is like we did in the previous example.
let userDefaults = UserDefaults.standard
if let defaultValues = readPropertyList() {
userDefaults.register(defaults: defaultValues)
}
That's everything you need to know about registering default values to UserDefaults.
You can easily support sarunw.com by checking out this sponsor.
AI Grammar: Correct grammar, spell check, check punctuation, and parphrase.
Related Resource
Read more article about Swift, UserDefaults, or see all available topic
Enjoy the read?
If you enjoy this article, you can subscribe to the weekly newsletter.
Every Friday, you'll get a quick recap of all articles and tips posted on this site. No strings attached. Unsubscribe anytime.
Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading and see you next time.
If you enjoy my writing, please check out my Patreon https://www.patreon.com/sarunw and become my supporter. Sharing the article is also greatly appreciated.
Become a patron Buy me a coffee Tweet ShareHow to save/export an image in Mac Catalyst
Learn how to lets users save an image outside of your app’s sandbox.
Reduce boilerplate code with an automatic synthesis of Equatable and Hashable conformance
Equatable and Hashable are two essential protocols in the Swift world. Let's learn an old Swift feature that you might forget.