Home > Enterprise >  Append array replaces items
Append array replaces items

Time:07-15

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)
    }
}
  • Related