Testable @AppStorage
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.