Testable @AppStorage

Petr Pavlík
2 min readOct 30, 2021

--

AppStorage is a property wrapper to simplify working with UserDefaults when using SwiftUI. You can check the vague apple docs on this topic, and luckily, there’s Hacking With Swift docs to save the day.

It seems like a convenient API to save you some time, but can you reasonably mock it? Now why would you want to mock it? SwiftUI previews are awesome, you can render multiple states of your views side by side to see what it looks like. Well, as long as you can mock those states.

Let’s jump to an example, I want to create a SwiftUI view that will render “Hello Petr” if I’m signed in and a log in button if I’m not.

struct AccountView: View {    // Note that optional values are iOS 15+, and no, it doesn't 
//support Codable types
@AppStorage("profileName") var profileName: String?
var body: some View { if let profileName = profileName { Text("Hello, \(profileName)!") } else { Button("Log in") { // TODO: log in } } }}

Now, how can I render both states in my preview side-by-side? You can overwrite the instance of UserDefaults AppStorage will use.

struct AccountView_Previews: PreviewProvider {    static var previews: some View {        let previewUserDefaults: UserDefaults = {            let d = UserDefaults(suiteName: "preview_user_defaults")!            d.set("Petr", forKey: "profileName")            return d        }()        AccountView()            .previewLayout(.fixed(width: 320, height: 100))        AccountView()            .previewLayout(.fixed(width: 320, height: 100))            .defaultAppStorage(previewUserDefaults)        }}

And here you have it, utilizing SwiftUI previews to it’s full potential.

--

--

Petr Pavlík

Staff iOS engineer by day, https://indiepitcher.com by night. I’ve also made http://swiftpack.co, npm for server-side swift