If you wish to use State properties with the new Preview macro, you'll have to create a wrapper for it:
#Preview(body: {
Preview()
})
private struct Preview: View {
@State private var isOn: Bool = true
var body: some View {
Toggle(
isOn: $isOn,
label: EmptyView.init
)
.labelsHidden()
}
}
Not only does this clutter the codebase, but it forces you to use arbitrary names, in case of multiple previews per file.
That's why, type declaration can be nested directly within the macro:
#Preview(body: {
struct Preview: View {
@State private var isOn: Bool = true
var body: some View {
Toggle(
isOn: $isOn,
label: EmptyView.init
)
.labelsHidden()
}
}
return Preview()
})
However, the macro has a problem compiling, when we attach availability attributes to it—
@available(iOS 17.0, *)
#Preview(body: {
struct Preview: View {
@State private var isOn: Bool = true
var body: some View {
Toggle(
isOn: $isOn,
label: EmptyView.init
)
.labelsHidden()
}
}
return Preview()
})
—which is strange, since simple previews with availability checks compile just fine:
@available(iOS 17.0, *)
#Preview(body: {
Text("Hello World")
})
The compiler throws the following error:
Compiling failed: 'Preview' is only available in iOS 17.0 or newer.
Are there any alternatives out there, instead of relying on an external type declaration shown in the first snippet?
A workaround I found is to check
#availableinside the preview closure: