I'm trying to append an array on a tap gesture, but it seems that it replaces any item in the array with the current one.
The Array and functions:
class ChipsViewModel: ObservableObject {
@Published var selectedCategories = [String]()
func appendArray(title:String) {
selectedCategories.append(title)
}
func removeFromArray(title:String){
if let index = selectedCategories.firstIndex(of: title) {
selectedCategories.remove(at: index)
}
}
}
The button itself:
@ObservedObject var viewModel = ChipsViewModel()
let systemImage: String
let titleKey: String
@State var isSelected: Bool
var body: some View {
HStack {
...
}.onTapGesture {
isSelected.toggle()
if(isSelected){
viewModel.appendArray(title: titleKey)
} else if (!isSelected){
viewModel.removeFromArray(title: titleKey)
}
print(viewModel.selectedCategories)
}
}
Not really sure why is this happening, it worked when i implemented a binding foreach, but using that setup the chips don't work as needed.
CodePudding user response:
The State
needs to be initialized, like
let systemImage: String
let titleKey: String
@State var isSelected: Bool = false // << here !!
CodePudding user response:
It looks like you are trying to keep state in sync in two places at the same time, it is usually not a good idea. It is best to keep it your view model
class ChipsViewModel: ObservableObject {
@Published var selectedCategories = [String]()
func isSelected(_ title: String) -> Bool {
selectedCategories.contains(title)
}
func toggleSelection(_ title: String) {
if let index = selectedCategories.firstIndex(of: title) {
selectedCategories.remove(at: index)
} else {
selectedCategories.append(title)
}
}
}
and then your View
gets simpler and the state (i.e. whether a title is selected or not) cannot get out of sync:
@StateObject var viewModel = ChipsViewModel()
let systemImage: String
let titleKey: String
var isSelected: Bool {
viewModel.isSelected(titleKey)
}
var body: some View {
HStack {
//...
}
.onTapGesture {
viewModel.toggleSelection(titleKey)
}
}