The issue has been solved
For example, currently, a Codable that is serialized to a String
is stored as "foo"
because we serialize it as JSON. It would be nice to make it just foo
(without the double-quotes).
The following values could be improved when serialized from a Codable:
- String (for example string enum):
"foo"
=> foo
- Arrays are currently stored as a serialized string in a
String
plist type. We should really use a native plist Array
type.
- Dictionaries with string keys should also be stored as a native
Dictionary
plist type.
This is a breaking change, so it would have to be an opt-in and we could make it the default in the next major version (with still a way to opt-out so existing projects can upgrade).
This is not an easy issue. You are expected to have advanced knowledge of Swift and Codable.

I stored some key with 3.1.1 after upgrade to 4.x these key changed from without quote version to with quote version, which is quite buggy for me.
posted by aalenliang over 4 years ago
@aalenliang Could you share the raw UserDefaults value before and after v4?
I have not seen this problem myself.
posted by sindresorhus over 4 years ago
Here is my related code, simplified version:
extension Defaults.Keys {
static let deviceId = Key<String?>("SettingsModule.deviceId", default: nil)
}
public static var deviceId: String = {
let id = Defaults[.deviceId] // <--- set break point here.
?? UIDevice.current.identifierForVendor?.uuidString
?? UUID().uuidString
if Defaults[.deviceId] == nil {
Defaults[.deviceId] = id
}
return id
}
in Debug using simulator, iPhone 11 Pro Max (13.6)
using Defaults 3.1.1:
(lldb) po Defaults[.deviceId]
â–¿ Optional<String>
- some : "7B88D8F4-F82C-4413-BE53-D3E26A2F41BC"
(lldb) po UserDefaults.standard.string(forKey: "SettingsModule.deviceId")
â–¿ Optional<String>
- some : "\"7B88D8F4-F82C-4413-BE53-D3E26A2F41BC\""
using Defaults 4.0.0:
(lldb) po Defaults[.deviceId]
â–¿ Optional<String>
- some : "\"7B88D8F4-F82C-4413-BE53-D3E26A2F41BC\"" // <--- extra quote mark here.
(lldb) po UserDefaults.standard.string(forKey: "SettingsModule.deviceId")
â–¿ Optional<String>
- some : "\"7B88D8F4-F82C-4413-BE53-D3E26A2F41BC\""
posted by aalenliang over 4 years ago
@aalenliang I assume you had it as Key<String?>("SettingsModule.deviceId", default: nil)
even in v3.1.1? Because that syntax was not supported then. It should have been OptionalKey<String>("SettingsModule.deviceId")
. Since you passed an optional when it was not supported in v3.1.1, it was treated as a non-native value and got quoted even though it shouldn't have. You'll need to do a simple migration yourself. This is not something Defaults
can handle.
posted by sindresorhus over 4 years ago
Yes, I use Key<Sting?>
since I start using this framework, which is about a year ago. Since the compiler allows me to do this, I always doing this.
Ok, I think my issue is irrelevant with this issue, I'll upgrade to the latest version and handle the migration myself.
Thanks!
posted by aalenliang over 4 years ago
posted by issuehunt-app[bot] over 4 years ago 
posted by issuehunt-app[bot] almost 4 years ago 
posted by sindresorhus almost 4 years ago 
How do I get the improved representations to work? My enum-based strings are still being saved as <string>"value"</string>
.
posted by tonyarnold over 3 years ago
Ah, belay that - it's working. I needed to kill a process on my end that was interfering with the updated definition. I had been using Codable
, but I can see that's unnecessary for simple string-based enums now. Thanks!
posted by tonyarnold over 3 years ago