Sometimes we may need to call an action every time a toggle changes instead of relying purely on a state property to keep our toggle up to date. Luckily this is easy to do. An action can be called when a toggle is updated (or any control that takes in a binding, such as a slider) and a state property will be used to display the state in the control.

To achieve this, we can create a custom binding in our view body like so:

var body: some View {
    let binding = Binding {
        toggleValue
    } set: {
        doSomething(with: $0)
    }

    Toggle(isOn: binding) {
        Text("Toggle")
    }
}

Within our doSomething method, we can then perform any logic we want to and also set the value of toggleValue. A full example would look something like this:

struct ContentView: View {

    @State private var toggleValue: Bool = false

    var body: some View {
        let binding = Binding {
            toggleValue
        } set: {
            doSomething(with: $0)
        }

        Toggle(isOn: binding) {
            Text("Toggle")
        }
    }

    private func doSomething(with value: Bool) {
        toggleValue = value
        // Any additional work here
    }
}

I found this functionality useful recently when working with physical BLE devices. I could keep the UI up to date while sending data to the device. If something went wrong, the value of the UI could easily be reverted and an error message displayed. This is just one use case but there are tonnes more uses for calling a method when a toggle changes.

Remember this can be applied to any sort of SwiftUI binding, for example when a slider changes, or any custom views you create yourself.

Thanks for reading!