I'm currently working on a Swift project where I register default values to two different UserDefaults
suites: the standard suite and a custom suite. However, I'm seeing an unexpected (potentially correct) overlap between them. I've tried finding information in the docs about this but couldn't.
Here's a simplified version of my code:
Note:
com.domain.custom
isn't the app bundle ID, I was only mimicking App Groups reverse domain without thegroup.
and using a domain not the same as my app ID
import SwiftUI
@main
struct TestApp: App {
init() {
// Register defaults for standard UserDefaults
UserDefaults.standard.register(defaults: [
"standardA": "Standard A value"
])
// Register defaults for custom UserDefaults with suiteName
if let customUserDefaults = UserDefaults(suiteName: "com.domain.custom") {
customUserDefaults.register(defaults: [
"customA": "Custom A value"
])
}
// Function to print all keys
func printCustomKeys(for userDefaults: UserDefaults) {
let allKeys = userDefaults.dictionaryRepresentation()
print("Custom keys for UserDefaults suite:")
allKeys.forEach { key, value in
print("\(key) = \(value)")
}
}
// Usage
printCustomKeys(for: UserDefaults.standard)
if let customUserDefaults = UserDefaults(suiteName: "com.domain.custom") {
printCustomKeys(for: customUserDefaults)
}
}
var body: some Scene {
WindowGroup { .. }
}
}
The output I get is:
Custom keys for UserDefaults suite:
AppleLocale = en_AU
standardA = Standard A value
...
customA = Custom A value
...
Custom keys for UserDefaults suite:
customA = Custom A value
standardA = Standard A value
...
I register "standardA" to UserDefaults.standard
and "customA" to a custom suite (com.domain.custom
). But when I print the keys, I see both "standardA" and "customA" in both suites, even though I expected "standardA" to only exist in the standard suite and "customA" only in the custom suite.
My question: Why are keys from UserDefaults.standard
appearing in my custom suite and vice versa?
Is there some behaviour in UserDefaults
that I'm misunderstanding? I was under the impression that standard and custom suites should be completely isolated.
This is because you use register
. From the docs,
Adds the contents of the specified dictionary to the registration domain.
If there is no registration domain, one is created using the specified dictionary, and
registrationDomain
is added to the end of the search list.The contents of the registration domain are not written to disk; you need to call this method each time your application starts.
So using register
will always add the keys and values to the registration domain. That is the domain with the name UserDefaults.registrationDomain
. The UserDefaults
object you create will always search the registration domain, in addition to the domain indicated by suitName
.