I'm trying to make a macro PreviewBrands that will take a @ViewBuilder and then apply various modifiers to it, resulting in four outputs (like SwiftUI's Preview but with 4 outputs).
Then, in the expansion(... for DeclarationMacro I do
...
let brands = [
"Brand1",
"Brand2",
"Brand3",
"Brand4"
]
// Generate the previews for each brand
let generatedPreviews = brands.map { brand in
"""
struct BrandPreview_\(previewName)_\(brand): PreviewProvider {
static var previews: some View {
\(bodyExpr.statements)
.environmentObject(Context.\(brand.lowercased())Context)
.previewDisplayName("\(brand)")
}
}
"""
}.joined(separator: "\n")
let result: DeclSyntax =
"""
#if DEBUG
\(raw: generatedPreviews)
#endif
"""
return [result]
This gives me: Declaration name 'BrandPreview_CalibrationIntroView_Brand1' is not covered by macro 'PreviewBrands' and so on...
And I can't use: @freestanding(declaration, names: arbitrary) because of: 'declaration' macros are not allowed to introduce arbitrary names at global scope
I would recommend not trying to make preview macros for Xcode. Even though below I only mention the macro, the same goes for PreviewProvider in how Xcode looks for them.
I wouldn't leverage macros, or the #Preview macro, but you could accomplish something similar with PreviewSnapshots.
You define an array of configurations and a closure to create the preview for a given configuration, and it will generate a preview for each element in the array. It also provides functions for capturing snapshot tests for each preview in unit tests.
The most basic approach to using it would be to declare the array of configurations directly in the PreviewProvider like this:
Clean names doesn't matter that much, since it's not really visible.
Thanks for the tip! I thought I tried that but can't remember it working yesterday, but now it does work!! But - even tho it appears as if it generates those structs correctly, nothing appears on the canvas :( Thanks for the input tho!