Home How to Extend your SwiftUI Previews to Stub Data
Post
Cancel

How to Extend your SwiftUI Previews to Stub Data

Intro

In SwiftUI, the preview provider is a powerful tool for previewing your app’s user interface during the development process. By default, the preview provider generates a live preview of your SwiftUI code, allowing you to see changes in real-time. However, when working with dynamic data or external dependencies, it can be useful to set up your preview provider to use stub data or a dependency injection (DI) container. In this article, we will explore how to set up your SwiftUI preview provider with stub data using a DI container.

DI Container and Stub Data

Before we begin, let’s briefly go over what a DI container is and how it can be used in SwiftUI. A DI container is a tool used to manage dependencies in an application by injecting them into objects that need them. In the context of SwiftUI, a DI container can be used to provide dependencies such as data models, API clients, or networking services to your views and view controllers. Using a DI container can make your code more modular, testable, and maintainable.

Stub data, on the other hand, is pre-generated data used for testing and development purposes. By using stub data in your preview provider, you can avoid relying on live data during development and testing, which can be slower, less predictable, and less secure.

Extending SwiftUI Preview Provider

Let’s say we have a cryptocurrency app. And we have the need to inject a coin object into a lot of our app’s views, so we can preview and make sure the view looks correct and the data is displayed. To setup our SwiftUI preview provider for this DI scenario, we can leverage singleton to create a DI container for our preview provider like below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//DI Container
class DeveloperPreview {
    
    static let shared = DeveloperPreview()
    private init() {}
    
    let coin = CoinModel(
        id: "bitcoin",
        symbol: "btc",
        name: "Bitcoin",
        image: "https://assets.coingecko.com/coins/images/1/large/bitcoin.png?1547033579",
        currentPrice: 61408,
        marketCap: 1141731099010)
}


// extend PreviewProvider with a computed property of our DI container
extension PreviewProvider {
    
  static var dev: DeveloperPreview {
      return DeveloperPreview.shared
  }
    
}

Here, we are extending the SwiftUI PreviewProvider protocol with a computed property named dev, which returns an instance of our DeveloperPreview DI container. This implementation effectively makes our stubbed coin data globally available for use in all of our SwiftUI previews. This neat little trick now allows us to use pre-defined data in our previews, making development easier and faster.

Now let’s see it in action, let’s say we need to preview a view called CoinDetailView, a view that takes in a coin as a single dependency. Now with our setup, we can easily use our DI container’s coin property to provide stub data for our view like below:

1
2
3
4
5
6
7
8
9
10
11
12
13
struct CoinDetailView: View {
  let coin: CoinModel

  var body: some View {
    Text(coin.name)
  }
}
struct CoinDetailView_Previews: PreviewProvider {
    
    static var previews: some View {
        CoinDetailView(coin: dev.coin) // look at how clean that is 🌟
    }
}

Conclusion

As you can see, by extending SwiftUI preview provider with stub data and a DI container, you can make your development process faster, more predictable, and more modular. You can extend this approach to more complex views and applications by defining additional dependencies in your DI container and using them in your views and view controllers.

Hope you found this helpful ❤️✌️

This post is licensed under CC BY 4.0 by the author.