Search code examples
iosswiftswiftuiuserdefaults

Trying to save data in UserDefaults and show them in list view


Trying to save some data in UserDefaults but I'm getting nil in the view. I don't know where is the problem

This is my code in ContentView:

var saveButton: some View {
    Button("Save Meal") {
        let meal = Meal(name: self.mealGenerator.currentMeal!.name,
                        imageUrlString: self.mealGenerator.currentMeal!.imageUrlString,
                        ingredients: self.mealGenerator.currentMeal!.ingredients,
                        instructions: self.mealGenerator.currentMeal!.instructions,
                        area: self.mealGenerator.currentMeal!.area,
                        category: self.mealGenerator.currentMeal!.category)
        self.savedMeals.meals.append(meal)
        self.savedMeals.saveMeals()
    }

This is my class I'm trying to save:

class SavedMeals: ObservableObject {
    @Published var meals: [Meal]

    func saveMeals() {
        if let encoded = try? JSONEncoder().encode(meals) {
            UserDefaults.standard.set(encoded, forKey: "Meals")
        }
     }
    
     init() {
        if let meals = UserDefaults.standard.data(forKey: "Meals") {
            if let decoded = try? JSONDecoder().decode([Meal].self, from: meals) {
                self.meals = decoded
                return
            }
        }
        self.meals = []
    }
}

And I'm trying to list in a view:

struct SavedMealsView: View {

    @ObservedObject var savedMeals: SavedMeals

    var body: some View {
        NavigationView {
            List(savedMeals.meals) { meal in
                Text(meal.name)
            }
            .navigationBarTitle("Saved Meals", displayMode: .inline)
        }
    }
}

Solution

  • You do meals = [] at the end of your init regardless of what you decode. Perhaps this will work better:

    init() {
        if data = UserDefaults.standard.data(forKey: "Meals") {
            do {
                meals = try JSONDecoder().decode([Meal].self, from: meals)
            } catch {
                assertionFailure("Oops!")
                meals = [] 
            }
        } else {
            meals = []
        }
    }