Reputation: 10226
I have some Toggle Switches in a row but I want to prevent switches ON if already two of them is ON. And showing an Alert that maximum 2 of them is allowed to ON. Here is my code:
struct PreventToggle: View {
@State private var isCheckeds = [false, true, true, false, false, false]
@State var showAlert = false
var body: some View {
let numberOfTrue = isCheckeds.filter{$0}.count
showAlert = numberOfTrue > 2
return ForEach(0 ..< isCheckeds.count) { id in
Toggle("Switch \(id)", isOn: self.$isCheckeds[id])
.alert(isPresented: self.$showAlert) {
Alert(title: Text("Maximum Limit!"), message: Text("Maximum limit is: 3"), dismissButton: .default(Text("Got it")))
}
}
}
}
Upvotes: 3
Views: 1566
Reputation: 3438
This is how it can work:
struct PreventToggle: View {
@State private var isCheckeds = [false, true, true, false, false, false]
@State var lastSelected = -1
func alertBinding() -> Binding<Bool> {
Binding<Bool>(
get: {
let numberOfTrue = self.isCheckeds.filter{$0}.count
return numberOfTrue > 2 && self.lastSelected != -1
},
set: { _ in }
)
}
func toggleBinding(for index: Int) -> Binding<Bool> {
Binding<Bool>(
get: {
return self.isCheckeds[index]
},
set: { bool in
self.isCheckeds[index] = bool
self.lastSelected = index
}
)
}
var body: some View {
VStack {
ForEach(0 ..< isCheckeds.count) { id in
Toggle("Switch \(id)", isOn: self.toggleBinding(for: id))
}
}
.alert(isPresented: alertBinding()) {
Alert(title: Text("Maximum Limit!"),
message: Text("Maximum limit is: 3"),
dismissButton: .default(Text("Got it"), action: {
self.isCheckeds[self.lastSelected] = false
self.lastSelected = -1
})
)
}
}
}
Upvotes: 3
Reputation: 8126
try this:
...but then the message never disappears, because you never set the toggle values back to 2...so this is what you still have to do. and maybe you should do your check inside the toggle action and not when building the view.
struct ContentView: View {
@State private var isCheckeds = [false, true, true, false, false, false]
@State var showAlert = false
var body: some View {
let numberOfTrue = isCheckeds.filter{$0}.count
OperationQueue.main.addOperation {
self.showAlert = numberOfTrue > 2
}
return VStack {
ForEach(0 ..< isCheckeds.count) { id in
Toggle("Switch \(id)", isOn: self.$isCheckeds[id])
.alert(isPresented: self.$showAlert) {
Alert(title: Text("Maximum Limit!"), message: Text("Maximum limit is: 3"), dismissButton: .default(Text("Got it")))
}
}
}
}
}
Upvotes: -1