A new tag is in town. How to use bindings directly in Xcode Previews
Posted: | Author: Jörn | Filed under: Swift, SwiftUI, Tools, Xcode | Tags: Binding, Xcode, Xcode Preview | No Comments »Xcode Previews are great. To be able to immediately see how changes in your code are rendered immensely speeds up the development process and makes developing UI elements real fun.
What makes previews even better is that they automatically become interactive when your View has a @State. Consider this code:
struct ColorSwitcher: View {
@State var color: Color
var body: some View {
VStack {
HStack {
Button("Red") { color = .red }
Button("Green") { color = .green }
Button("Blue") { color = .blue }
}
color.frame(width: 200, height: 200)
}
}
}
#Preview {
ColorSwitcher(color: .red)
}
With automatically gives you a preview that is interactive. When you click on the buttons you can see that the colors change:

So far, so easy.
Things become a bit more complicated when your view uses a @Binding instead of a @State. This is really common when you implement custom UI controls:
struct ColorSwitcher: View {
@Binding var color: Color
var body: some View {
VStack {
HStack {
Button("Red") { color = .red }
Button("Green") { color = .green }
Button("Blue") { color = .blue }
}
color.frame(width: 200, height: 200)
}
}
}
#Preview {
ColorSwitcher(color: .constant(.red))
}
Now you need to instantiate a Binding inside the #Preview. The only way to do this without having access to a @State is to use a constant binding. This works but now the interactivity is gone. You can still tap the buttons, but the colors do not change (because the binding is a constant binding that cannot change).

Previously (before iOS17) you help yourself by adding a preview wrapper that can have a @State:
struct ColorSwitcherPreviewWrapper: View {
@State var color: Color = .red
var body: some View {
ColorSwitcher(color: $color)
}
}
#Preview {
ColorSwitcherPreviewWrapper()
}
This works, but it not a very elegant solution.
iOS17 to the rescue!
Now we can use the new @Previewable tag to allow a dynamic property to appear inline in a preview.
#Preview {
@Previewable @State var color = Color.red
ColorSwitcher(color: $color)
}
This makes the preview interactive again.
