简体   繁体   中英

SwiftUI - ObservableObject doesn't cause update

I have a class called SocialMealplan that looks like the following:

public class SocialMealplan : Identifiable, ObservableObject {
    public var id : String {
        return owner.id
    }
    @Published public var owner : YKUser
    @Published public var mealplan : Mealplan
    
    init(owner : YKUser, mealplan : Mealplan) {
        self.owner = owner
        self.mealplan = mealplan
    }
}

I then have the following code:


struct MealPlanView: View {

    @ObservedObject var currentMealplan: SocialMealplan = SocialMealplan(owner: YKUser.none, mealplan: Mealplan.none)

    var body: some View {
    /* ... */

        ForEach(self.currentMealplan.mealplan.meals, id: \.self) { (meal) in
            VStack {
                NavigationLink(destination: SelectRecipeView(completion: self.updatedMealplan, date: meal.date)) {
                    MealplanRow(meal: .constant(meal))
                }
            }
        }.onAppear {
            self.refreshMealplan()
        }

    /* ... */
    }

    func refreshMealplan() {
        // Get the mealplan from the server
        self.currentMealplan.mealplan = newMealplan
    }
}

The problem is that when I run this code it gets the mealplan, but when it tries to assign the variable nothing happens. refreshMealplan is called and the variable is assigned, but nothing changes on the UI and the view doesn't refresh to reflect the new data.

(Neither does anything happen when I reassign the owner variable)

A new SocialMealPlan object currentMealPlan is being created and initialized every time the view needs to be redrawn/recreated. So one object triggers the update (by assignment to one of the Published vars), but the new updated view refers to its own new freshly initialized copy of currentMealPlan .

Option 1: Make currentMealPlan a @StateObject (so one copy representing a state is kept and referred to). ie @StateObject var currentMealplan = SocialMealplan(owner: YKUser.none, mealplan: Mealplan.none)

Option 2: Or keep the @ObservedObject, but create it before and outside th view. But if other views also need to refer to the currentMealPlan , create one before the View and pass it as an environment variable. ie MealPlanView().environmentObject(currentMealPlan) and then in the view @EnvironmentObject var currentMealPlan: SocialMealPlan

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM