简体   繁体   中英

How do I pass in an Environment Object to my ViewModel SwiftUI

I am using a function to get recipes from a database via an API endpoint. It takes in 3 parameters, fat, carbs, protein and I want these values to be equal to my environment object (or a calculation of two environment objects) fatGoal - fatProgress etc. However in my viewModel I get the following error when trying to use my environment object:

Thread 1: Fatal error: No ObservableObject of type UserInfoModel found. A View.environmentObject(_:) for UserInfoModel may be missing as an ancestor of this view.

This is my ViewModel service file:

import SwiftUI
import Combine
import Foundation

class MealViewModel: ObservableObject {
    
    @Published var nutrients: [RecipieAPI] = []
    
    @EnvironmentObject var person: UserInfoModel
    
    
    @State public var fat = 0
    @State public var carbs = 0
    @State public var protein = 0


    
    init() {
        
        fetchNutrients()


    }
    
    func fetchNutrients() {
        NetworkServices.fetchNutrients(maxProtein: self.person.recipeNutrientsSearch.protein , maxFat: self.person.recipeNutrientsSearch.fat,  maxCarbs: self.person.recipeNutrientsSearch.carb, number: 4) { (nutrients, error) in
            if let error = error {
                print(error)
            } else {
                if let nutrientList = nutrients as? [RecipieAPI] {
                    self.nutrients = nutrientList
                }
            }
        }
    }
}

The error is called in

NetworkServices.fetchNutrients(maxProtein: self.person.recipeNutrientsSearch.protein , maxFat: self.person.recipeNutrientsSearch.fat,  maxCarbs: self.person.recipeNutrientsSearch.carb, number: 4) { (nutrients, error) in

Any help would be greatly appreciated

Edit Content View:

import SwiftUI

struct ContentView: View {

    
    //Instantiating an object of UserInfo Model (referenced in App.swift too 
    @EnvironmentObject var person: UserInfoModel
    

    
    init() {
        //Setting appearance of UI colour
        UITabBar.appearance().backgroundColor = ColourManager.UIColour1
    }
    
    var body: some View {
        
        
        TabView {
            ProfileView().tabItem ({
                Text("Profile")
            }).tag(0)
            
            TrackerView().tabItem ({
                Text("Tracker")
            }
            ).tag(1)

            
            AddView().tabItem ({
                Text("Add")
            }).tag(2)
            
            MealView().tabItem ({
                Text("Meals")
            }).tag(3)
        }.accentColor(ColourManager.Colour3)
        .environmentObject(UserInfoModel())

        
        }

    }

Environment Object class: UserinfoModel:

import Foundation

class UserInfoModel: ObservableObject {
    
    
    struct UserInfo: Identifiable {
        var id = UUID()
        var firstName: String
        var height: Double
        var weight: Double
        var gender: String
        var age: Double
        var activityLevel: String
        var BMR: Double
        
    }
    
    struct AddedFoods:Identifiable{
        var name: String = ""
        var totalCals: Double = 0
        var totalProtein: Double = 0
        var totalCarbs: Double = 0
        var totalFat: Double = 0
        var id = UUID().uuidString
       //Your other properties
    }
    
    struct DailyCalorieGoals: Identifiable{
        var id = UUID()
        var calorieGoal: Double
        var fatGoal: Double
        var proteinGoal: Double
        var carbGoal: Double

    }
    
    struct CurrentCalorieProgress: Identifiable{
        var id = UUID()
        var calorieProgress: Double
        var fatProgress: Double
        var carbProgress: Double
        var proteinProgress: Double

    }
    
    struct SearchRecipeCalories: Identifiable{
        var id = UUID()
        var fat: Int
        var carb: Int
        var protein: Int

    }
    
    @Published var personUserInfo = UserInfo.init(firstName: "",  height: 0, weight: 0, gender: "", age: 0, activityLevel: "", BMR: 0)
    @Published var personDailyCalorieGoals = DailyCalorieGoals.init(calorieGoal: 2400, fatGoal: 40, proteinGoal: 40, carbGoal: 40)
    @Published var personCurrentCalorieProgress = CurrentCalorieProgress.init(calorieProgress: 1200, fatProgress:   12, carbProgress: 5, proteinProgress: 30)
    
    @Published var  recipeNutrientsSearch = SearchRecipeCalories.init(fat: 0, carb: 0, protein: 0)
    
    
}

EnvironmentObjects must be supplied by anscestor views!


 import SwiftUI
    
    @main
    struct pro2App: App {    // <<: Here: your app name!
        var body: some Scene {
            WindowGroup {
                ContentView()
                    .environmentObject(MealViewModel()) // <<: Here!
                    .environmentObject(UserInfoModel.shared) // <<: Here!
            }
        }

}

    class MealViewModel: ObservableObject {
    
    @Published var nutrients: [RecipieAPI] = []
    
    let person: UserInfoModel.shared   // <<: Here
    
    
    @State public var fat = 0
    @State public var carbs = 0
    @State public var protein = 0


    
    init() {
        
        fetchNutrients()


    }
    
    func fetchNutrients() {
        NetworkServices.fetchNutrients(maxProtein: self.person.recipeNutrientsSearch.protein , maxFat: self.person.recipeNutrientsSearch.fat,  maxCarbs: self.person.recipeNutrientsSearch.carb, number: 4) { (nutrients, error) in
            if let error = error {
                print(error)
            } else {
                if let nutrientList = nutrients as? [RecipieAPI] {
                    self.nutrients = nutrientList
                }
            }
        }
    }
}

class UserInfoModel: ObservableObject {
    
static let shared: UserInfoModel = UserInfoModel() // <<: Here
    
    struct UserInfo: Identifiable {
        var id = UUID()
        var firstName: String
        var height: Double
        var weight: Double
        var gender: String
        var age: Double
        var activityLevel: String
        var BMR: Double
        
    }
    
    struct AddedFoods:Identifiable{
        var name: String = ""
        var totalCals: Double = 0
        var totalProtein: Double = 0
        var totalCarbs: Double = 0
        var totalFat: Double = 0
        var id = UUID().uuidString
       //Your other properties
    }
    
    struct DailyCalorieGoals: Identifiable{
        var id = UUID()
        var calorieGoal: Double
        var fatGoal: Double
        var proteinGoal: Double
        var carbGoal: Double

    }
    
    struct CurrentCalorieProgress: Identifiable{
        var id = UUID()
        var calorieProgress: Double
        var fatProgress: Double
        var carbProgress: Double
        var proteinProgress: Double

    }
    
    struct SearchRecipeCalories: Identifiable{
        var id = UUID()
        var fat: Int
        var carb: Int
        var protein: Int

    }
    
    @Published var personUserInfo = UserInfo.init(firstName: "",  height: 0, weight: 0, gender: "", age: 0, activityLevel: "", BMR: 0)
    @Published var personDailyCalorieGoals = DailyCalorieGoals.init(calorieGoal: 2400, fatGoal: 40, proteinGoal: 40, carbGoal: 40)
    @Published var personCurrentCalorieProgress = CurrentCalorieProgress.init(calorieProgress: 1200, fatProgress:   12, carbProgress: 5, proteinProgress: 30)
    
    @Published var  recipeNutrientsSearch = SearchRecipeCalories.init(fat: 0, carb: 0, protein: 0)
    
    
}

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