Why my viewModel does not update my view?

85 Views Asked by At

I'm trying to use conditional views but when i change my published variable, the view does not switch to the other, i have to make it reappear, i don't know if it's a SwiftData issue or what but i'm clueless here, it's the first time happening to me

My view :

struct DiaryView: View {
    @Environment(\.modelContext) private var modelContext
    @Query var macros: [Macros]
    @ObservedObject var viewModel = DiaryViewModel()
    
    private func initView() {
        viewModel.fetchMacros(macros, viewModel.currentDate)
        if viewModel.dailyMacros == nil {
            modelContext.insert(Macros())
            viewModel.fetchMacros(macros, viewModel.currentDate)
        }
    }
    
    var body: some View {
        VStack {
            DailyDateView(date: $viewModel.currentDate)
                .onChange(of: viewModel.currentDate) { _ , newValue in
                    viewModel.fetchMacros(macros, newValue)
                }
            if viewModel.dailyMacros == nil {
                VStack(alignment: .center) {
                    Spacer()
                    Text("No data")
                        .bold()
                        .font(.title)
                    Spacer()
                }
            } else {
                HStack {
                    ProgressCircleView(number1: viewModel.dailyMacros!.carbs, number2: viewModel.totalCarbs, color: Color.brown, size: 80, title: NSLocalizedString("Carbs", comment: ""))
                    ProgressCircleView(number1: viewModel.dailyMacros!.fat, number2: viewModel.totalFat, color: Color.orange, size: 80, title: NSLocalizedString("Fat", comment: ""))
                    ProgressCircleView(number1: viewModel.dailyMacros!.proteins, number2: viewModel.totalProteins, color: Color.red, size: 80, title: NSLocalizedString("Proteins", comment: ""))
                }
                
                HStack {
                    ProgressView()
                        .progressViewStyle(CustomProgressBar(number1: viewModel.dailyMacros!.calories, number2: viewModel.totalCalories, color: Color.purple, width: 300, title: "Calories"))
                }
                .padding()
                
                HStack {
                    IncrementButton(number: $viewModel.incrementCarbs, width: 20, color: Color.brown)
                    IncrementButton(number: $viewModel.incrementFat, width: 20, color: Color.orange)
                    IncrementButton(number: $viewModel.incrementProteins, width: 20, color: Color.red)
                }
                
                HStack {
                    CustomButtonView(action: {
                        viewModel.add()
                    }, label: "Appliquer", color: Color.blue, width: 200, height: 50)
                }
            }
            Spacer()
        }
        .onAppear {
            initView()
        }
    }
}

My viewModel :

class DiaryViewModel: ObservableObject {
    
    private enum Constants {
        static let quickAddMaxNumber: CGFloat = 999
        static let quickAddMinimalNumber: CGFloat = 0
    }
    
    @Published var incrementCarbs: CGFloat
    @Published var incrementProteins: CGFloat
    @Published var incrementFat: CGFloat
    @Published var dailyMacros: Macros?
        
    var totalCarbs: CGFloat
    var totalFat: CGFloat
    var totalProteins: CGFloat
    var totalCalories: CGFloat
    
    @Published var currentDate: Date
    
    init(incrementCarbs: CGFloat = 0, incrementProteins: CGFloat = 0, incrementFat: CGFloat = 0, dailyMacros: Macros? = nil, currentDate: Date = .now) {
        self.incrementCarbs = incrementCarbs
        self.incrementProteins = incrementProteins
        self.incrementFat = incrementFat
        self.dailyMacros = dailyMacros
        
        self.totalCarbs = (UserDefaults.standard.string(forKey: "carbs")?.toCGFloat())!
        self.totalFat = (UserDefaults.standard.string(forKey: "fat")?.toCGFloat())!
        self.totalProteins = (UserDefaults.standard.string(forKey: "proteins")?.toCGFloat())!
        self.totalCalories = (UserDefaults.standard.string(forKey: "calories")?.toCGFloat())!
        
        self.currentDate = currentDate
    }
    
    func add() {
        guard let macros = dailyMacros else {
            return
        }
        
        if checkQuickEntrys() {
            
            macros.carbs += incrementCarbs
            macros.fat += incrementFat
            macros.proteins += incrementProteins
            
            let caloriesFromCarbs = incrementCarbs * 4
            let caloriesFromFat = incrementFat * 9
            let caloriesFromProteins = incrementProteins * 4
            
            macros.calories += caloriesFromCarbs + caloriesFromFat + caloriesFromProteins
            
        }
        resetMacroIncrements()
    }

    private func resetMacroIncrements() {
        incrementCarbs = 0
        incrementFat = 0
        incrementProteins = 0
    }
    
    private func checkQuickEntrys() -> Bool {
        guard let macros = dailyMacros,
              macros.carbs + incrementCarbs >= Constants.quickAddMinimalNumber,
                  macros.fat + incrementFat >= Constants.quickAddMinimalNumber,
                  macros.proteins + incrementProteins >= Constants.quickAddMinimalNumber else {
                return false
            }
        
        guard let macros = dailyMacros,
                  macros.carbs < Constants.quickAddMaxNumber,
                  macros.fat < Constants.quickAddMaxNumber,
                  macros.proteins < Constants.quickAddMaxNumber else {
                return false
            }
        
        return true
    }

    func fetchMacros(_ macros: [Macros], _ date: Date) {
        self.dailyMacros = macros.first(where: { Calendar.current.isDate($0.date, equalTo: date, toGranularity: .day) }) ?? nil
    }
}

I switched the dailyMacros to the view with a @State property wrapper but nothing changed

0

There are 0 best solutions below