I have issue with SwiftUI. I am attempting to create mutually exclusive toggles for filtering. At least one of the toggles should at all times be selected. So if you click an already selected toggle, it should stay selected.
I have tried using published UserData and then setting the other toggles in a didSet section for all variables. This approach, however, simply crashes the program, when i click any of the toggles.
The UI looks like this
The code for the SwiftUI file can be seen her:
struct DSTScrollView: View {
@EnvironmentObject private var userData: UserData
var body: some View {
ScrollView(.vertical, showsIndicators: true){
VStack{
Text("Befolkning og Valg Tabeller")
.font(.subheadline)
.multilineTextAlignment(.center)
HStack {
VStack (alignment: .leading){
Text("Folketal (BY2)")
HStack{
Toggle(isOn: $userData.DSTSelections.BY2_allAges){
Text("Alle aldre")
}
Toggle(isOn: $userData.DSTSelections.BY2_5Year){
Text("5-års aldersgrupper")
}
Toggle(isOn: $userData.DSTSelections.BY2_10Year){
Text("10-års aldersgrupper")
}
}
}
Spacer()
}
.padding(.leading, 8)
}
}
.frame(maxWidth: 580, minHeight: 300)
.border(Color.black)
}
}
The code for the UserData can be seen here:
final class UserData: ObservableObject {
@Published var DSTSelections: DSTSelection = DSTSelection()
}
final class DSTSelection: ObservableObject{
var BY2_allAges: Bool = false{
didSet{
BY2_10Year = false
BY2_5Year = false
BY2_allAges = true
}
}
var BY2_5Year: Bool = false{
didSet{
BY2_allAges = false
BY2_10Year = false
BY2_5Year = true
}
}
var BY2_10Year: Bool = true {
didSet{
BY2_allAges = false
BY2_5Year = false
BY2_10Year = true
}
}
}
The trouble is with you model class DTSelection
, in your didSet
code you are setting the other properties to new values which will trigger their didSet
and so on leading to an infinite loop.
This is my refactoring of your model class where I have introduced an enum and a new private property to keep track of the currently selected value. I have also changed the public properties to be computed properties
enum DSTSelectionEnum {
case BY2_allAges
case BY2_5Year
case BY2_10Year
}
final class DSTSelection: ObservableObject{
private var trueOption: DSTSelectionEnum = .BY2_allAges
var BY2_allAges: Bool {
get {
trueOption == .BY2_allAges
}
set {
trueOption = .BY2_allAges
}
}
var BY2_5Year: Bool {
get {
trueOption == .BY2_5Year
}
set {
trueOption = .BY2_5Year
}
}
var BY2_10Year: Bool {
get {
trueOption == .BY2_10Year
}
set {
trueOption = .BY2_10Year
}
}
}
This should work without any changes to your view code