Property wrappers to remove boilerplate code in Swift

Property wrappers were first introduced during WWDC 2019 and come with Xcode 11 in Swift 5. It’s a neat addition to the Swift library and allows us to remove a lot of boilerplate code which we probably all have written in our projects.


Property wrappers and UserDefaults


extension UserDefaults {

    public enum Keys {
        static let hasSeenAppIntroduction = "has_seen_app_introduction"

    var hasSeenAppIntroduction: Bool {
        set {
            set(newValue, forKey: Keys.hasSeenAppIntroduction)
        get {
            return bool(forKey: Keys.hasSeenAppIntroduction)


UserDefaults.standard.hasSeenAppIntroduction = true

guard !UserDefaults.standard.hasSeenAppIntroduction else { return }

Now as this seems to be a nice solution, it could easily end up being a large file with a lot of defined keys and properties. The code contains a lot of repetitive parts and asks for a way to make this easier. The @propertyWrapper keyword introduced with the property wrappers implementation solves this.

Using property wrappers to remove boilerplate code

Taking the above example we can easily rewrite this code and remove a lot of overhead. For that, we have to create a new property wrapper which we will call UserDefault. This will eventually allow us to define a property as being a user default property.

struct UserDefault<T> {
    let key: String
    let defaultValue: T

    init(_ key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue

    var wrappedValue: T {
        get {
            return UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
        set {
            UserDefaults.standard.set(newValue, forKey: key)


Unfortunately, we can’t use the property wrapper in an extension on UserDefaults. Instead, we have to create a new wrapper object which we call UserDefaultsConfig in this example. The reason for this is that class stored properties are not supported in class extensions.

The new wrapper can be defined as followed:

struct UserDefaultsConfig {
    @UserDefault("has_seen_app_introduction", defaultValue: false)
    static var hasSeenAppIntroduction: Bool

As you can see we can use the initializer from the defined property wrapper. We pass in the same key as we used before and we set the default value to false. Using this new property is simple:

UserDefaultsConfig.hasSeenAppIntroduction = false
print(UserDefaultsConfig.hasSeenAppIntroduction) // Prints: false
UserDefaultsConfig.hasSeenAppIntroduction = true
print(UserDefaultsConfig.hasSeenAppIntroduction) // Prints: true

Adding more properties using the same wrapper


struct UserDefaultsConfig {
    @UserDefault("has_seen_app_introduction", defaultValue: false)
    static var hasSeenAppIntroduction: Bool

    @UserDefault("username", defaultValue: "Antoine van der Lee")
    static var username: String

    @UserDefault("year_of_birth", defaultValue: 1990)
    static var yearOfBirth: Int


Other usage examples

Property wrappers are used throughout the default Swift APIs as well. The new @State and @Binding keys are an example of this. Another idea could be to create a wrapper for thread-specific writing and reading:

@ThreadSpecific var localPool: MemoryPool

Or, as some might find handy, a way to define command line actions:

var minimum: Int


Property wrappers are a great way to remove some boilerplate in your code. The above example is only one of many scenarios in which it can be useful. Try it out yourself and remove some code in your projects using Xcode 11.
