SwiftUI Previews
Since the introduction of SwiftUI Previews have been one of the biggest updates. Instead of having to start the simulator we can now create custom views and see them in the preview with the content staying up-to-date as we make changes.
The default preview that shows when we create a new SwiftUI view is already amazing as it allows us to quickly change things like the color scheme, orientation, and dynamic type. But there is so much more we can do with SwiftUI Previews that allow us to quickly test our newly create views!
Content
- Showing previews with data
- Creating multiple previews
- Customizing previews name and device type
- Customizing the previews size
1. Showing Previews with Data
To have some example we can work with we can use the final code from Creating an Image Card in SwiftUI displayed below:
import SwiftUI
struct ImageCard: View {
var body: some View {
VStack(alignment: .leading, spacing: 16.0) {
Image("Workout")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 240, height: 200)
cardText.padding(.horizontal, 0)
}
.background(.white)
.clipShape(RoundedRectangle(cornerRadius: 24.0))
.shadow(radius: 8.0)
}
var cardText: some View {
VStack(alignment: .leading, spacing: 4.0) {
Text("Evening Workout").font(.headline)
HStack(spacing: 4.0) {
Image(systemName: "clock.arrow.circlepath")
Text("50 min")
}.foregroundColor(.gray)
}.padding()
}
}
Currently the image card is very static and we can’t easily create multiple cards with different content. To fix this we can just introduce the image, the title, and the duration as variables and use those.
Before the preview will render we need to now pass those values to the preview:
import SwiftUI
struct ImageCard: View {
var image: String
var title: String
var time: String
var body: some View {
VStack(alignment: .leading, spacing: 16.0) {
Image(self.image) // NEW: use variable instead of name
// ...
cardText
.padding(.horizontal, 0)
}
// ...
}
var cardText: some View {
VStack(alignment: .leading, spacing: 4.0) {
Text(self.title) // NEW: use variable instead of title
// ...
HStack(spacing: 4.0) {
Image(systemName: "clock.arrow.circlepath")
Text(self.time) // NEW: use variable instead of time
}.foregroundColor(.gray)
}// ...
}
}
struct ImageCard_Previews: PreviewProvider {
static var previews: some View {
// NEW: pass variables to the preview
ImageCard(image: "Yoga", title: "Lunch-Time Yoga", time: "30 min")
}
}
This makes it super easy to quickly for example changing the image, and directly see the results in the preview.
Note: You can use the same views also in the preview. For example, we could wrap the ImageCard in a VStack and add a second ImageCard with different values!
struct ImageCard_Previews: PreviewProvider {
static var previews: some View {
VStack {
ImageCard(image: "Dance", title: "Evening Dance", time: "50 min")
ImageCard(image: "Yoga", title: "Lunch-Time Yoga", time: "30 min")
}
}
}
2. Creating multiple Previews
Just putting different previews beside each other in a Stack works but isn’t always the best way if we want to test views with different data completely separately.
To create a second preview we can simply use the Group View and then add up to 10 previews. To add a Group you can either replace the previously created VStack with Group, or you can always command left click on a view and then select “Group” to embed the View in a Group.
struct ImageCard_Previews: PreviewProvider {
static var previews: some View {
Group {
ImageCard(image: "Dance", title: "Evening Dance", time: "50 min")
ImageCard(image: "Yoga", title: "Lunch-Time Yoga", time: "30 min")
}
}
}
On top of your preview you will now see a second label with the same name where you can switch between the two previews!
3. Customizing Previews Name and Device Type
Having different previews is great but except for maybe showing different data there is not much difference so far. However, we can easily set what device the preview should show. For example, we want to see the first image card on an iPhone and the second on an iPad. We can do so by just changing the .previewDevice().
struct ImageCard_Previews: PreviewProvider {
static var previews: some View {
Group {
ImageCard(image: "Dance", title: "Evening Dance", time: "50 min")
.previewDevice(PreviewDevice(rawValue: "iPhone 14 Pro"))
ImageCard(image: "Yoga", title: "Lunch-Time Yoga", time: "30 min")
.previewDevice(PreviewDevice(rawValue: "iPad Pro (11-inch) (4th generation)"))
}
}
}
If we want to test more devices we can just add another ImageCard and change to Device.
Note: You can get a list of all supported preview device names by running the following command in your terminal:
xcrun simctl list devicetypes
Quickly changing the preview like this is amazing for testing your layout on different devices. For a little bit of organization we can even name the previews differently to easily show which preview is displaying what.
struct ImageCard_Previews: PreviewProvider {
static var previews: some View {
Group {
ImageCard(image: "Dance", title: "Evening Dance", time: "50 min")
.previewDevice(PreviewDevice(rawValue: "iPhone 14 Pro"))
.previewDisplayName("ImageCard on iPhone")
ImageCard(image: "Yoga", title: "Lunch-Time Yoga", time: "30 min")
.previewDevice(PreviewDevice(rawValue: "iPad Pro (11-inch) (4th generation)"))
.previewDisplayName("ImageCard on iPad")
}
}
}
4. Customizing the Previews Size
While it is great that we can test a view directly on multiple devices, sometimes we just want to preview the actual view and don’t get distracted how it looks in a device.
Instead of just getting the full device we can just define a size for the preview with .previewLayout(). We can pass three values to this method:
- device
- fixed(width: CGFloat, height: CGFloat)
- sizeThatFits
struct ImageCard_Previews: PreviewProvider {
static var previews: some View {
ImageCard(image: "Dance", title: "Evening Dance", time: "50 min")
.previewLayout(.fixed(width: 300, height: 350))
}
}
If you want to test it without a device you could for example use .previewLayout(.sizeThatFits), which will wrap it around the content, or set a size yourself with .fixed().
Note: Setting the frame size to a fixed size won’t show any effect in live preview mode. Change to Selectable to see the change.
Thank You! ❤️
First of all, congratulations if you made it until here and I hope you found some of the tips helpful! 👍
And if you did enjoy this story please follow me for more stories! 😊