Overriding UserDefaults for improved productivity

UserDefaults within apps are used to store data related to user configurations. It’s an easily accessible data store for saving states, statistics, and other app-related data.

Launch arguments are passed to the application on launch and can be used to alter the application for debugging purposes. It’s often used by Apple to allow developers to enable specific debugging modes, like in Core Data. The same we can do ourselves to enable certain debug modes in our apps.

An example case: UserDefaults to trigger an app introduction

A common use-case for using launch arguments is to force enable an introduction screen during development. Without this, we would need to reinstall the app every time so that the introduction screen shows up.

An example code implementation could look as follows:

var shouldShowIntroduction: Bool {
    /// Use a launch argument to always skip the app introduction.
    if ProcessInfo.processInfo.arguments.contains("-skipAppIntroduction") {
        return false
    }

    /// Use a launch argument to always show the app introduction.
    if ProcessInfo.processInfo.arguments.contains("-requireAppIntroduction") {
        return true
    }

    /// No launch arguments found, read from the user defaults.
    return UserDefaults.standard.bool(forKey: "hasSeenAppIntroduction") == false
}

In this case, we have three options:

  • Force-skip the introduction using the -skipAppIntroduction launch argument
  • Force-enable the introduction using the -requireAppIntroduction launch argument
  • Read the value from the user defaults

Although this works, it will easily fill up your launch arguments and it requires extra code with potential bugs. It would be much easier to simply override the user defaults directly. If so, we could have a simple code implementation like:

import SwiftUI

@main
struct UserDefaultsLaunchArgumentsApp: App {
    var body: some Scene {
        WindowGroup {
            if UserDefaults.standard.bool(forKey: "hasSeenAppIntroduction") == false {
                IntroductionView()
            } else {
                ContentView()
            }
        }
    }
}

Using launch arguments to override user defaults

Overriding user defaults using launch arguments can be done in the scheme editor. In this case, we’d like to force-enable the introduction screen by overriding the hasSeenAppIntroduction user defaults value.

You can do this by following these steps:

  1. Select your scheme and click Edit Scheme... or use Product ➞ Scheme ➞ Edit Scheme...
  2. Go to Run and open the Arguments tab
  3. Add a new value to Arguments Passed On Launch
  4. In this example, add: -hasSeenAppIntroduction 0
Overriding user defaults using launch arguments
Overriding user defaults using launch arguments

Launch arguments need to be passed using the dash sign in front of the key. The value can be added after the key. In this case, we will use a zero which equals to false for booleans. We could’ve used a value of 1 if we would like to force disable the introduction screens.

Conclusion

And that’s it! We’ve enabled our app introduction for development while not touching our code. A custom launch argument allows us to alter the value of the user defaults so that the introduction is always shown.

If you like to improve your Xcode knowledge, even more, check out the Xcode category page. Feel free to contact me or tweet to me on Twitter if you have any additional tips or feedback.

Thanks!