(2022/04/01: updated and expanded)
NSUserDefaults → UserDefaults
In the beginning, when Cocoa was hot (circa 2001), there was already NSUserDefaults, a thoughtful API for the seemingly simple task of persisting preference settings.
Swift (since 2014) gave it a cleaner name (UserDefaults, without the NS prefix), but it also created new expectations that the plain old class was not delivering:
- strong type checking
- easy value types usage
- modern Swiftness, etc.
This is where Swiftified UsersDefaults libraries come in. Here we look at a few of them:
- SwiftyUserDefaults: "Modern Swift API for NSUserDefaults"
- Defaults: "Swifty and modern UserDefaults"
- Foil: "A lightweight property wrapper for UserDefaults done right"
(TLTR? Jump to the summary table.)
usage
declarations & definitions
- 1. SwiftyUserDefaults
- 2. Defaults
- 3. Foil
import SwiftyUserDefaults
extension DefaultsKeys {
var userName: DefaultsKey<String> { .init("userName", defaultValue: "") }
var quality: DefaultsKey<Double> { .init("quality", defaultValue: 0.8) }
var launchCount: DefaultsKey<Int?> { .init("launchCount") } // optional
}
import Defaults
extension Defaults.Keys {
static let userName = Key<String>("userName", default: "")
static let quality = Key<Double>("quality", default: 0.8)
static let launchCount: Key<Int?>("launchCount") // optional
}
import Foil
class Settings {
@WrappedDefault(key: "userName") var userName: String = ""
@WrappedDefault(key: "quality") var quality: Double = 0.8
@WrappedDefaultOptional(key: "launchCount") var launchCount: Int? // optional
}
The first two libraries both define Keys in an extension; Defaults' approach looks a bit cleaner.
Foil, being the newest kid on the block, takes advantage of Swift's Property Wrappers. Using it involves defining actual usable variables (instead of just keys) in your own class (or struct).