Jun 16, 2020

Computed State in SwiftUI view

In my App that I recently published to App store I wanted to let users control the sound. There are small sound effects on various user actions. The App is a Board game called Ludo) where players take turns to roll dice and race their tokens. To make controls more granular I decided to have a separate toggles for dice roll and token move sound. As I thought users might only want to turn off these two frequent sounds and not all which are infrequent. So it was like implementing a master toggle to control everything and two other toggles that you can turn off/on individually


Something like this

Master toggle

Now it is not possible to implement it with three individual states (using @State) and passing their projected value (using $) to Toggle. The solution is easy but not something we usually do, so I figured it is worth sharing it in a short tip. Here is how I built it.


struct BindingDemo: View {
    @State private var sound: Bool = true
    @State private var moveSound: Bool = true
    @State private var diceSound: Bool = true
    
    private var soundBinding: Binding<Bool> {
        Binding(get: {
            self.sound
        }) {
            self.sound = $0
            self.moveSound = $0
            self.diceSound = $0
        }
    }

    private var moveSoundBinding: Binding<Bool> {
        Binding(get: {
            self.moveSound && self.sound
        }) {
            self.moveSound = $0
        }
    }
    private var diceSoundBinding: Binding<Bool> {
        Binding(get: {
            self.diceSound && self.sound
        }) {
            self.diceSound = $0
        }
    }

    var body: some View {
        VStack {
            Toggle(isOn: soundBinding) {
                Text("Sound?")
            }
            Toggle(isOn: moveSoundBinding) {
                Text("Move Sound?")
            }
            Toggle(isOn: diceSoundBinding) {
                Text("Dice Sound?")
            }
        }
        .padding()
    }
}

Here is the link to my App if you are curious. The App is available for iPhone, iPad and macOS. The app link takes you to the Mac or iOS App store depending on which platform you are in.

Tagged with: