One of the great features of SwiftUI is the Xcode support for previewing views without launching the simulator. This speeds up development but where do you keep your preview data? If you’re not careful your view code can become cluttered with sample data.
Preview Data
The tight integration Xcode provides between the declaration of a SwiftUI view and its preview gives you fast feedback as you make changes. At first I tended to create the sample data for the preview along with the preview. For example, here’s my preview of a view that displays a Country
with some sample model data created in the preview provider:
That approach makes it easier to play with the data but it soon gets out of hand. I also want sample data when displaying countries in a list:
I created the rows in my list with country cell views which also need some of the same sample data:
I’m also likely to want variations on the sample data for different edge cases. For example, how does my cell layout work when the country name wraps over multiple lines:
Without doing anything special I’m already copying and pasting variations of the same preview data multiple times. This is tiresome and a pain to maintain.
Development Assets
An approach I’ve seen from a few iOS developers and Apple engineers during WWDC videos is to create the preview data alongside the model. This might be in a standalone type or as an extension on the model (or view model):
extension Country {
/// United Kingdom
static let uk = Country(id: 2635167, name: "United Kingdom",
capital: "London", continent: "Europe", currency: "GBP", area: 244820,
north: 59.3607741849963, south: 49.9028622252397, east: 1.7689121033873,
west: -8.61772077108559, population: 66488991, visited: true),
/// ...
}
This cleans up the preview provider and allows the data to be used by any of the views:
struct CountryView_Previews: PreviewProvider {
static var previews: some View {
return NavigationView {
CountryView(country: Country.uk)
}
}
}
It’s also a convenient place to create collections of model data that will make our list previews more realistic. For example, loading a larger set of country data from a JSON file:
extension Country {
static var countries = loadPreviewData("countryInfo.json")
static private func loadPreviewData(_ name: String) -> [Country] { ... }
}
Collecting the preview data into one place is a good first step. The next step is to exclude this data from your release builds by letting Xcode know they are development assets.
You may have already noticed that if you create a new SwiftUI project Xcode creates a Preview Content
folder for you and adds an empty asset catalog:
Xcode treats this asset catalog differently from your apps main asset catalog. Xcode will not include any assets you add to the preview asset catalog in your release builds. We are not limited to this one preview asset catalog. Xcode treats any files we add to the Preview Content
folder as development assets.
You can add your own folders if you want. Add the files or folders to the Xcode project as usual then add them the list of development assets in the settings for the target:
In my example, I added the country preview data files to the existing Preview Content
folder:
You can also use the development assets in your unit tests, just remember to add the assets to the targets:
Read More
See this video from WWDC 2020 for a brief discussion (starting at around 9 mins) of using Xcode development assets for preview data: