Arturo
Arturo

Reputation: 4180

@Published is not getting updated, State problem? - SwiftUI

Right now I have to call the function (calculatePortfolioGrossBalance) 3 times for the value to update, what am I doing wrong in the state logic?

In the code below, when I call in an init the function calculatePortfolioGrossBalance() it returns empty [], I have to call it 3 times for the value to update, However... if I print the values of getTokenBalancesModel in the line DispatchQueue.main.async { I can see the values are there, so how come in calculatePortfolioGrossBalance are not?

final class TokenBalancesClassAViewModel: ObservableObject {
    
    @Published var getTokenBalancesModel: [TokenBalancesItemsModel] = [TokenBalancesItemsModel]()
    @Published var portfolioGrossBalance: String = "0.0"
    
    
    func calculatePortfolioGrossBalance() {
        getTokenBalances()
        
        DispatchQueue.main.async {
            var totalBalance: Double = 0
            
            for item in self.getTokenBalancesModel {
                totalBalance += Double(item.quote!)
            }
            
            self.portfolioGrossBalance = String(format:"%.2f", totalBalance)
            print(self.portfolioGrossBalance)
        }
    }
    
    func getTokenBalances() {
        guard let url = URL(string: "someUrlHeidiGaveMe") else {
            print("Invalid URL")
            return
        }
        
        print("Calling getTokenBalances() ...")
        
        AF.request(url, method: .get).validate().responseData(completionHandler: { data in
            do {
                guard let data = data.data else {
                    print("Response Error:", data.error as Any)
                    return
                }
                
                let apiJsonData = try JSONDecoder().decode(TokenBalancesModel.self, from: data)
                DispatchQueue.main.async {
                    self.getTokenBalancesModel = apiJsonData.data.items
                }
            } catch {
                print("ERROR:", error)
            }
        })
    }
}

Upvotes: 0

Views: 150

Answers (1)

you need to read up on using asynchronous functions, how to set them up and how to use them. This is important. Try something like this (untested):

final class TokenBalancesClassAViewModel: ObservableObject {
    
    @Published var getTokenBalancesModel: [TokenBalancesItemsModel] = [TokenBalancesItemsModel]()
    @Published var portfolioGrossBalance: String = "0.0"

    func calculatePortfolioGrossBalance() {
        getTokenBalances() { isGood in
            if isGood {
                var totalBalance: Double = 0
                for item in self.getTokenBalancesModel {
                    totalBalance += Double(item.quote!)
                }
                self.portfolioGrossBalance = String(format:"%.2f", totalBalance)
                print(self.portfolioGrossBalance)
            }
        }
    }
    
    func getTokenBalances(completion: @escaping (Bool) -> Void) {
        guard let url = URL(string: "someUrlHeidiGaveMe") else {
            print("Invalid URL")
            completion(false)
            return
        }
        
        print("Calling getTokenBalances() ...")
        
        AF.request(url, method: .get).validate().responseData(completionHandler: { data in
            do {
                guard let data = data.data else {
                    print("Response Error:", data.error as Any)
                    completion(false)
                    return
                }
                
                let apiJsonData = try JSONDecoder().decode(TokenBalancesModel.self, from: data)
                DispatchQueue.main.async {
                    self.getTokenBalancesModel = apiJsonData.data.items
                    completion(true)
                }
            } catch {
                print("ERROR:", error)
                completion(false)
            }
        })
   
    }
}

Upvotes: 1

Related Questions