Type-Safe User Defaults in Swift
To declare a key, write a
structconforming to theTSUDprotocol. Inside, implement a singlestaticproperty calleddefaultValuewhich contains the value to be returned ifUserDefaultsdoesn't contain a value:struct fontSize: TSUD { static let defaultValue = 12.0 }
This is an interesting take that uses a new type for each key and then creates the string key from the type’s name. I have been using a simpler system that looks something like this:
// register
extension MJTUserDefaults.IntDefault {
static let cacheSize = key("CacheSize", 2000)
}
// query
MJTDefaults[.cacheSize]
I like this because it’s compact to register a bunch of keys in sequence and because putting them all into the same type works well for auto-completion.
Update (2017-10-09): Jean-David Gadina (tweet):
The solution I propose is to automate the wrapping code on runtime, using reflection. This used to be done with the Objective-C runtime. With Swift, it’s even easier through the use of the
Mirrorclass.
Update (2017-10-14): Nicolas Bouilleaud:
#function, as per the documentation, “inside a property getter or setter it is the name of that property”. Unfortunately, that means we can’t write:struct Prefs_ { var foo = TSUD<Date>() }because in this context,
#functionwould bePrefs_. Usinglazy, I guess, implicitely creates a closure, which is called as a getter the first time the property is accessed, and#functionisfoo.