Kurt Mueller
Kurt Mueller

Reputation: 3224

Toggling a Binding<Bool> with a SwiftUI button action

I'm trying to create a simple labeled checkbox in SwiftUI that toggles an isChecked when the button is pressed. It's very similar to the example in Apple's Binding documentation:

import SwiftUI

struct LabeledCheckbox: View {
    var labelText: String
    @Binding var isChecked: Bool

    var checkBox: Image {
        Image(systemName: isChecked ? "checkmark.circle" : "circle")
    }

    var body: some View {
        Button(action: {
            self.isChecked.toggle()
        }) {
            HStack {
                checkBox
                Text(labelText)
            }
        }
    }
}

struct LabeledCheckbox_Previews: PreviewProvider {
    static var previews: some View {
        LabeledCheckbox(labelText: "Checkbox", isChecked: .constant(false))
    }
}

Unfortunately, when I interact with this button in "Live Preview" mode, the button action doesn't seem to actually toggle isChecked. You can view that here. I put a print(isChecked ? "checked" : "unchecked") debug statement in the action closure and observed in the console output the that isChecked was never being toggled.

I've also attempted to get LabeledCheckboxto be toggable by passing in a state variable in LabeledCheckbox_Previews. The button is still not toggable.

struct LabeledCheckbox_Previews: PreviewProvider {
    @State private static var isChecked = false

    static var previews: some View {
        LabeledCheckbox(labelText: "Checkbox", isChecked: $isChecked)
    }
}

What am I doing wrong? Any help is appreciated.

Upvotes: 2

Views: 6485

Answers (1)

Kevin Renskers
Kevin Renskers

Reputation: 5912

You need to provide mutable state, not a constant value. For example like this.

import SwiftUI

struct LabeledCheckbox: View {
  var labelText: String
  @Binding var isChecked: Bool

  var checkBox: Image {
    Image(systemName: isChecked ? "checkmark.circle" : "circle")
  }

  var body: some View {
    Button(action: {
      self.isChecked.toggle()
    }) {
      HStack {
        checkBox
        Text(labelText)
      }
    }
  }
}

struct ContentView: View {
  @State private var isChecked = false

  var body: some View {
    LabeledCheckbox(labelText: "Checkbox", isChecked: $isChecked)
  }
}

struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}

Upvotes: 4

Related Questions