UserPreferences: A wrapper for UserDefaults

UserDefaults is a great way to store and retrieve app settings and user preferences in iOS apps. However, working with it can sometimes be a bit verbose, especially if you need to store or retrieve multiple values.

Fortunately, Swift allows us to add a subscript to UserDefaults to make working with it much more convenient:

extension UserDefaults {
    subscript<T>(key: String) -> T? {
        get { return object(forKey: key) as? T }
        set(newValue) {
            set(newValue, forKey: key)
            synchronize()
        }
    }
}

This makes it easier to store and retrieve values from the UserDefaults.

Something that I usually like to do in my projects, is to create a wrapper around UserDefaults to centralize all the code related to preferences inside it:

With this class, you can now store and retrieve user preferences and settings using a convenient subscript syntax, like this:

UserPreferences.shared[.onBoardingSeen] = true
let value: Bool? = UserPreferences.shared[.onBoardingSeen]

You could also add some basic unit tests for this class:


A great tip from SwiftLee is to create an AppGroup for your app:

  1. Add the App Groups capability
  2. Create an static instance
    extension UserDefaults {
     static let group = UserDefaults(suiteName: "group.your.identifier")!
    }
    
  3. Use the instance:
    /// Initializes the UserPreferences object with a UserDefaults instance.
    init(userDefaults: UserDefaults = .group) {
     self.userDefaults = userDefaults
    }
    

Any app or extension configured with the same app group will now be able to read and write from the same UserDefaults instance.


The next iteration of the UserPreferences class would be to add some type-safe methods to retrieve the stored information.

I hope this tip helps you write more concise and readable code in your iOS apps!

UserPreferences: A wrapper for UserDefaults | manu.show
Tags: iOS testing
Share: Twitter LinkedIn