Hey everyone,
I ran into an interesting quirk while working on a SwiftUI project involving the #Preview macro. I tried using it to test my views under different conditions, much like I would with the PreviewProvider struct. However, I noticed some unexpected behavior. Let me show you the difference between the two approaches with a quick example:
struct Test_Previews: PreviewProvider {
static var previews: some View {
Group {
Text("First Preview")
.previewDisplayName("1")
Text("Second Preview")
.previewDisplayName("2")
}
}
}
This code should generate two previews in the canvas, each with a different name. And it works perfectly!
But when I use #Previews, things go differently:
#Preview {
Group {
Text("First Preview")
.previewDisplayName("1")
Text("Second Preview")
.previewDisplayName("2")
}
}
Instead of two previews, it only creates one, combining all the views into a single preview.
In trying to find a solution, I explored two avenues:
- Creating my own macro to mimic the struct's behavior.
- Understanding why the
#Preview macro doesn't behave as expected.
After some digging, here's what I found:
- Crafting a custom macro seems tricky because Xcode is responsible for opening the canvas, and it seems to rely on internal triggers like the
preview macro or explicit struct instantiation.
- The discrepancy with the original macro might stem from the type of closure it accepts. Despite documentation stating it should be a
@ViewBuilder, the macro's definition specifies a closure of type body: @escaping @MainActor() -> any View, without mentioning @ViewBuilder.
While using multiple #Preview instances can generate several previews, it gets tricky when testing constructs like ForEach, where reverting to the struct becomes necessary.
Overall, I don't see a good reason for the original macro to deviate from the struct's behavior.
Am I missing anything here? Let's discuss it in the comments.
5 Likes
If you're wondering about the purpose behind this functionality, it's primarily to enable testing of views with diverse input data.
Pippin
(Ethan Pippin)
3
Xcode does very special and proprietary things with the #Preview macro. For example, it declares an arbitrarily named (seemingly) at the global scope but the macro declaration doesn't declare any names.
Additionally, #Preview and preview providers are part of SwiftUI and these are the forums for the Swift language, so there won't be much help here.