I am in the beginning stages of developing an open-source utility for storing state in the Bundle UserDefaults
.
I'm encountering an issue when I add non-Codable
data types to my Dictionary
of [String: Any]
.
I need to be able to vet the data before trying to submit it, because the UserDefaults.set(_:)
method won't throw any errors. It just crashes.
So I want to make sure that the Dictionary
that I'm submitting is kosher.
I can't just check if it's Codable
, because it can sometimes say that it isn't, when the struct is actually good. (It's a Dictionary<String, Any>
, and I can cram all kinds of things in there).
I need to validate that the Dictionary
can produce a plist. If this were ObjC, I might use one of the NSPropertyListSerialization
methods to test the Dictionary
, but it appears as if this set of methods is not available to Swift.
According to the UserDefaults
docs, there are a specific set of types and classes that are "plist-studly."
I think testing each type in the list is unacceptable. I need to see if I can find a way to test that won't be screwed the first time Apple updates an OS.
Is there a good way to test a Dictionary<String, Any>
to see if it will make UserDefaults.set(_:)
puke?
The Property List type set of UserDefaults
is very limited. The supported types are
NSString
→ Swift String
NSNumber
→ Swift Int
, Double
or Bool
NSDate
→ Swift Date
NSData
→ Swift Data
Any
is not supported unless it represents one of the 4 value or 2 collection types.
Property List compliant collection types can be written to UserDefaults
with PropertyListSerialization
(even in Swift).
There are two protocols to serialize custom types to Data
Codable
can serialize structs and classes.NSCoding
can serialize subclasses of NSObject
.All types in the structs/classes must be encodable and decodable (means conform to the protocol themselves).
The APIs of PropertyListSerialization
/ PropertyListEncoder/-Decoder
and NSKeyed(Un)Archiver
provide robust error handling to avoid crashes.