What is a good way to bind a SwiftUI alert or action sheet to the optionality of a value type model property (show the view when the property is nil)?

Viewed 471

SwiftUI alerts and action sheets take Boolean bindings, but I want mine to display when a model property is nil. The model property is var servicePlayer: Player!, and I want an alert or action sheet to be presented when the tennis serving player is not yet selected (nil), but I'm not sure what would be a good way to approach this.

My model layer is composed of value type structs, so at the moment marking the property as @Published isn't an option. It doesn't sound worth it refactoring my whole model layer to a class reference type to be able to adopt Combine (I depend on the model instances being value type copies for undoing and redoing), but I may be wrong.

struct Match: Codable {
    ...
    var servicePlayer: Player!
    ...
}

.alert(isPresented: $isPresented) {
    Alert(title: Text("Who will serve?"),
              primaryButton: .default(Text("You")) {
                match.servicePlayer = .playerOne
            },
              secondaryButton: .default(Text("Opponent")) {
                match.servicePlayer = .playerTwo
            })
}

The $isPresented binding is just a placeholder. Since servicePlayer starts out nil, the idea is for the alert to be initially presented, but also reappear later in the tennis match when service player is nil again and yet to be selected.

1 Answers

As you probably understand, the isPresented parameter of .alert requires a Binding<Bool>.

I assume Match is a @State property in your view:

struct ContentView: View {
   @State var match: Match

   var body: some View { ... }
}

which means that when that changes, the view will recompute. This means that your particular case you can use Binding.constant(bool):

.alert(isPresented: .constant(match.servicePlayer == nil)) {
   Alert(...)
}

because the Alert will modify the state by changing match.

Related