Mutable Binding in SwiftUI Live Preview
If you need a value that can be changed in the live preview, I like to use this helper class:
struct BindingProvider<StateT, Content: View>: View {
@State private var state: StateT
private var content: (_ binding: Binding<StateT>) -> Content
init(_ initialState: StateT, @ViewBuilder content: @escaping (_ binding: Binding<StateT>) -> Content) {
self.content = content
self._state = State(initialValue: initialState)
}
var body: some View {
self.content($state)
}
}
Use it like so:
struct YourView_Previews: PreviewProvider {
static var previews: some View {
BindingProvider(false) { binding in
YourView(yourBindingVar: binding)
}
}
}
This allows you to test changing the binding in the live preview.
Updates to a @State
variable in a PreviewProvider
appear to not update the the read-only computed property previews
directly. The solution is to wrap the @State
variable in a test holder view. Then use this test view inside the previews
property so the Live Preview refreshes correctly. Tested and working in Xcode 11.2.1.
struct ChildView: View {
@Binding var itemName: String
var body: some View {
VStack {
Text("Name: \(itemName)")
Button(action: {
self.itemName = "different value"
}) {
Text("Change")
}
}
}
}
struct ChildView_Previews: PreviewProvider {
struct BindingTestHolder: View {
@State var testItem: String = "Initial"
var body: some View {
ChildView(itemName: $testItem)
}
}
static var previews: some View {
BindingTestHolder()
}
}