user14806416
user14806416

Reputation:

SwiftUI | Preview not updating on @Binding var value change

I am learning SwiftUI and tried to make a simple todo list but I'm having issues understanding why @Binding property doesn't update my preview.

The code is the following.

import SwiftUI

struct TodoRow: View {
    @Binding var todo: Todo

    var body: some View {
        HStack {
            Button(action: {
                todo.completed.toggle()
            }, label: {
                Image(systemName: todo.completed ? "checkmark.square" : "square")
            })
            .buttonStyle(.plain)

            Text(todo.title)
                .strikethrough(todo.completed)
        }
    }
}

struct TodoRow_Previews: PreviewProvider {
    static var previews: some View {
        TodoRow(todo: .constant(Todo.sampleData[0]))
    }
}

The preview doesn't update when I click the square button but the app works fine. Am I using it incorrectly?

EDIT: Even without .constant(#), the preview doesn't work.

struct TodoRow_Previews: PreviewProvider {
    @State private static var todo = Todo.sampleData[0]

    static var previews: some View {
        TodoRow(todo: $todo)
    }
}

Upvotes: 2

Views: 1767

Answers (1)

user14806416
user14806416

Reputation:

Found a solution in the article Testing SwiftUI Bindings in Xcode Previews.

In order for previews to change you must create a container view that holds state and wraps the view you're working on.

In my case what I've ended up doing was changing my preview to the following.

struct TodoRow_Previews: PreviewProvider {

    // A View that simply wraps the real view we're working on
    // Its only purpose is to hold state
    struct TodoRowContainer: View {
        @State private var todo = Todo.sampleData[0]

        var body: some View {
            TodoRow(todo: $todo)
        }
    }

    static var previews: some View {
        Group {
            TodoRow(todo: .constant(Todo.sampleData[0]))
                .previewDisplayName("Immutable Row")

            TodoRowContainer()
                .previewDisplayName("Mutable Row")
        }
    }
}

Upvotes: 9

Related Questions