Home > Net >  How to update @ObservedObject object while adding items to the class
How to update @ObservedObject object while adding items to the class

Time:01-24

I have 2 sections (ingredients selection and ingredient added). In the ingredient selection, i get all items from a json file. The goal is whenever i chose an ingredient from the ingredient selection, the item should be added to the ingredient added section. However the actual result is that I am able to add all ingredients in AddedIngredients. However my @ObservedObject var ingredientAdded :AddedIngredients indicates no items, so nothing in the section.

What am I missing in my logic? Is it because the @Published var ingredients = [Ingredient]() is from a struct which creates a new struct every time ? My understanding is that since AddedIngredients is a class, it should reference the same date unless I override it.

This my model:

import Foundation

struct Ingredient: Codable, Identifiable {
    let id: String
    let price: String
    let ajoute: Bool
}

class AddedIngredients: ObservableObject {


    @Published var ingredients = [Ingredient]()
}

The ingredient section that displays all ingredients:

struct SectionIngredientsSelection: View {
    let ingredients: [Ingredient]
    @StateObject var ajoute = AddedIngredients()
    var body: some View {
        Section(header: VStack {
            Text("Ajouter vos ingredients")

        }) {
            ForEach(ingredients){ingredient in
                HStack{
                    HStack{
                        Image("mais")
                            .resizable()
                            .frame(width: 20, height: 20)
                        Text(ingredient.id)
                    }
                    Spacer()
                    HStack{
                        Text(ingredient.price )
                        Button(action: {
                            ajoute.ingredients.append(ingredient)
                            print(ajoute.ingredients.count)
                        }){
                            Image(systemName: "plus")
                                .foregroundColor(Color(#colorLiteral(red: 0, green: 0.3257463574, blue: 0, alpha: 1)))
                        }
                    }
                }
            }
            .listRowBackground(Color.white)
            .listRowSeparator(.hidden)
        }
    }
}

Whenever I add an ingredient from the previous section, it should appear on this section.

struct SectionIngredientsSelected: View {
    @ObservedObject var ingredientAdded :AddedIngredients
        var body: some View {
            Section(header: VStack {
                HStack{
                    Text("Vos ingredients")
                        .textCase(nil)
                        .font(.headline)
                        .fontWeight(.bold)
                        .foregroundColor(.black)

                    Button(action: {print(ingredientAdded.ingredients.count)}, label: {Text("Add")})
                }
            }) {
                ForEach(ingredientAdded.ingredients){ingredient in
                    HStack{
                        HStack{
                            Image("mais")
                                .resizable()
                                .frame(width: 20, height: 20)
                            Text(ingredient.id)
                        }
                        Spacer()
                        HStack{
                            Text(ingredient.price )
                            Button(action: {
                            }){
                                Image(systemName: "xmark.circle")
                                    .foregroundColor(Color(#colorLiteral(red: 0, green: 0.3257463574, blue: 0, alpha: 1)))
                            }
                        }
                    }
                }
                .listRowBackground(Color.white)
                .listRowSeparator(.hidden)
            }
        }
    }

Main View

struct CreationView: View {
    let ingredients: [Ingredient] = Bundle.main.decode("Ingredients.json")
    var addedIngre: AddedIngredients
    var body: some View {
        ScrollView {
            VStack{
                VStack(alignment: .leading) {
                    Image("creation")
                        .resizable()
                        .scaledToFit()
                    Text("Slectionnez vos ingredients preferes").fontWeight(.light)
                    Divider()
                        .padding(.bottom)
                }
            }
        }
        List {
            SectionIngredientsSelected(ingredientAdded: addedIngre)
            SectionIngredientsSelection(ingredients: ingredients)

        }
    }
}

CodePudding user response:

You are creating two different instances of AddedIngredients. These do not synchronize their content with each other. The simpelest solution would be to pull the AddedIngredients up into CreationView and pass it down to the sub views.

So change your CreationView to:

struct CreationView: View {
    let ingredients: [Ingredient] = Bundle.main.decode("Ingredients.json")
    @StateObject private var addedIngre: AddedIngredients = AddedIngredients()

and:

SectionIngredientsSelected(ingredientAdded: addedIngre)
SectionIngredientsSelection(ingredients: ingredients, ajoute: addedIngre)

and SectionIngredientsSelection to:

struct SectionIngredientsSelection: View {
    let ingredients: [Ingredient]
    @ObservedObject var ajoute: AddedIngredients

Remarks:

It is not perfectly clear for me how CreationView aquires addedIngre. From your code it seems it gets somehow injected. If this is the case and you need it upward the view hierachy, change the @StateObject to @ObservedObject. But make sure it is initialized with @StateObject.

  • Related