I'm having an issue with my application. I am trying to toggle one switch, and when this switch is toggled, all the other switched get toggled to off. I have tried using the onChange method. This method works for 2 of the switches on and off, but not for 3 or more?
Here is my attempted code:
import SwiftUI
import ToastUI
struct ContentView: View {
@State var generatedNumber : Int = 0
@State var allNumbers : Bool = true
@State var evensOnly : Bool = false
@State var oddsOnly : Bool = false
var body: some View {
VStack {
Text("Your genenerated number:")
.font(.bold(.title)())
Text("\(generatedNumber)")
.font(.bold(.custom("Generated Number Size", size: 60))())
.foregroundColor(.cyan)
VStack{
Toggle("All numbers", isOn: $allNumbers)
.tint(.cyan)
.onChange(of: allNumbers) { newValue in
//When toggled, turn other switches off, but leave this one on
evensOnly = !newValue
oddsOnly = !newValue
}
Toggle("Even numbers only", isOn: $evensOnly)
.tint(.cyan)
.onChange(of: evensOnly) { newValue in
allNumbers = !newValue
oddsOnly = !newValue
}
Toggle("Odd numbers only", isOn: $oddsOnly)
.tint(.cyan)
.onChange(of: oddsOnly) { newValue in
allNumbers = !newValue
evensOnly = !newValue
}
}.padding(30)
.toggleStyle(.switch)
}
}
}
This is what I am getting:
Only one switch should be on at a time, and if a different one is toggled, to turn the other 2 off. The onChange method when doing this states: "action tried to update multiple times per frame." Does this mean that two @State reloads are trying to occur at execution times too close to each other? Please help me
As the first comment already said you got a retain cycle. To achieve your goal, there are many solutions to it. However, I would do it like that (see code snippet) using the MVVM pattern to achieve it.
struct ContentView: View {
@State var generatedNumber : Int = 0
@StateObject var viewModel: ContentViewModel = .init()
var body: some View {
VStack {
Text("Your genenerated number:")
.font(.bold(.title)())
Text("\(generatedNumber)")
.font(.bold(.custom("Generated Number Size", size: 60))())
.foregroundColor(.cyan)
VStack {
Toggle("All numbers", isOn: $viewModel.allNumbers)
.tint(.cyan)
Toggle("Even numbers only", isOn: $viewModel.evensOnly)
.tint(.cyan)
Toggle("Odd numbers only", isOn: $viewModel.oddsOnly)
.tint(.cyan)
}.padding(30)
.toggleStyle(.switch)
}
}
}
class ContentViewModel: ObservableObject {
@Published var allNumbers : Bool = true
@Published var evensOnly : Bool = false
@Published var oddsOnly : Bool = false
private var store: [AnyCancellable] = []
init() {
$allNumbers
.sink(receiveValue: {
guard $0 else { return }
self.evensOnly = false
self.oddsOnly = false
})
.store(in: &store)
$evensOnly
.sink(receiveValue: {
guard $0 else { return }
self.allNumbers = false
self.oddsOnly = false
})
.store(in: &store)
$oddsOnly
.sink(receiveValue: {
guard $0 else { return }
self.allNumbers = false
self.evensOnly = false
})
.store(in: &store)
}
}