Mohammed Riyadh
Mohammed Riyadh

Reputation: 1019

Swiftui User Multiple Selection To Array of Object

I have the following response from API

"features": [
        {
            "name": "Safety",
            "_id": "636a638959d10a2603b8d645",
            "values": [
                    Array of String
            ]
        },
        {
            "name": "Entertainment",
            "_id": "636a64312bbe0cd292a1ffc6",
            "values": [
                Array of String
            ]

Which I decode it with :

struct Feature : Codable , Hashable{
    var name : String = ""
    var values : [Value] = []
}

struct Value : Codable, Hashable{
    var value : String = ""
    var unit : String = ""
}

And in the view is render it like :

var body: some View {
        VStack{
            HStack{
                Text("Choose Your Features").font(Font.body.bold())
                Spacer()
            }.padding(.leading, 15)
            ScrollView(.vertical, showsIndicators: false){
                VStack{
                    
                    ForEach(Array(features.enumerated()), id: \.offset) { featureIndex, feature in
                        HStack{
                            Text(feature.name).font(Font.body.bold())
                            Spacer()
                        }.padding(.bottom , 10)
                        ScrollView(.horizontal, showsIndicators: false){
                            HStack(spacing : 10){
                                ForEach(Array(feature.values.enumerated()), id: \.offset) { valueIndex, value in
                                    
                                    FeatureCell(isSelected: $isSelected, value: value).onTapGesture{
                                        // here
                                    }
                                }
                                
                            }
                            Divider().padding(10)
                        }
                    }.padding(15)
                    
                }
            }
            
        }
    }

The user may select multiple item from each feature values list, Now Im really confused about how to store these selections in an array of features object again, I tried almost every thing like Array, Set and Dictionaries but could not reach any solution.

Update : This is the json object I should send back

   {
    "features": [
        {
            "Safety": [
                "value1",
                "value9",
                "value3"
            ]
        },
        {
            "Entertainment": [
                "value7",
                "value2",
                "value8"
            ]
        }
    ]
}

Any help or ideas will be much appreciated

Upvotes: 0

Views: 323

Answers (1)

Cheezzhead
Cheezzhead

Reputation: 336

You usually want to use a Set to store which items are selected. This set should be a State variable instantiated in the parent view. The onTapGesture closure will add or remove the value to the set. If the FeatureCell needs to know whether the value is selected, simply use the .contains method.

struct FeatureValueSelectionView: View {
    // The feature whose values we are displaying
    let feature: Feature

    // Note: You may have to manually conform Value to the Hashable protocol
    @State private var selectedValues = Set<Value>()

    var body: some View {
        ForEach(feature.values) { value in
            FeatureCell(selected: selectedValues.contains(value), value: value)
                .onTapGesture { selectedValues.toggle(value) }
        }
    }
}

For toggling a value in a set, I like to use this simple extension:

extension Set {
    public mutating func toggle(_ element: Element) {
        if self.contains(element) {
            self.subtract([element])
        } else {
            self.insert(element)
        }
    }
}

Upvotes: 1

Related Questions