Reputation: 957
I have a small swift application, which includes 3 functions.
getIncData()
, getExpData()
(which gets data from firebase and stores it in an array) and getLeftBudget()
which should calculate the total value of the array from getIncData()
- getExpData()
Here is how my code looks like
var income = [Double]()
var expenses = [Double]()
var totalIncome: Double = 0
var totalExpenses: Double = 0
func getIncData() {
let budgetDB = Database.database().reference().child("Income")
budgetDB.observe(.childAdded) { (snapshot) in
let snapshotValue = snapshot.value as! Dictionary<String, String>
let value = snapshotValue["Value"]!
self.income.append(Double(Int(value)!))
self.totalIncome = self.income.reduce(0, +)
self.incomeLabel.text = "Income: " + String(self.totalIncome) + " €";
}
}
func getExpData() {
let budgetDB = Database.database().reference().child("Expenses")
budgetDB.observe(.childAdded) { (snapshot) in
let snapshotValue = snapshot.value as! Dictionary<String, String>
let value = snapshotValue["Value"]!
self.expenses.append(Double(value)!)
self.totalExpenses = self.expenses.reduce(0, +)
self.expensesLabel.text = "Expenses: " + String(Double(self.totalExpenses)) + " €";
}
func getLeftBudget() {
let budgetLeft = self.totalIncome - self.totalExpenses
self.budgetMonth.text = "Budget left - \(String(budgetLeft))"
}
Now the self.totalIncome
and self.totalExpenses
inside the getLeftBudget
return 0. What's the best way to get the data from the functions into the third function so I could make the calculations?
P.S. The arrays are getting populated with the data from firebase and the calculations are done inside getIncData()
and getExpData()
Upvotes: 0
Views: 1000
Reputation: 2353
You are getting the values from asynchronous functions using budgetDB.observe
.
Then when you call getLeftBudget
you don't have the values in variables yet. You should implement a completion handler function.
This code is not tested, I just used a notepad to adapt as I'm out of office, but the idea is it.
var income = [Double]()
var expenses = [Double]()
var totalIncome: Double = 0
var totalExpenses: Double = 0
typealias returnCalc = (Bool) -> Void
func getIncData(completion: @escaping returnCalc) {
let budgetDB = Database.database().reference().child("Income")
budgetDB.observe(.childAdded) { (snapshot) in
let snapshotValue = snapshot.value as! Dictionary<String, String>
let value = snapshotValue["Value"]!
self.income.append(Double(Int(value)!))
self.totalIncome = self.income.reduce(0, +)
self.incomeLabel.text = "Income: " + String(self.totalIncome) + " €";
completion(true)
}
}
func getExpData(completion: @escaping returnCalc) {
let budgetDB = Database.database().reference().child("Expenses")
budgetDB.observe(.childAdded) { (snapshot) in
let snapshotValue = snapshot.value as! Dictionary<String, String>
let value = snapshotValue["Value"]!
self.expenses.append(Double(value)!)
self.totalExpenses = self.expenses.reduce(0, +)
self.expensesLabel.text = "Expenses: " + String(Double(self.totalExpenses)) + " €";
completion(true)
}
}
func getLeftBudget() {
getIncData { (completed) in
getExpData(completion: { (completed) in
let budgetLeft = self.totalIncome - self.totalExpenses
self.budgetMonth.text = "Budget left - \(String(budgetLeft))"
})
}
}
You can push a little the use of completion blocks and go straight forward using the function return value, avoiding context or global variables:
var income = [Double]()
var expenses = [Double]()
var totalIncome: Double = 0
var totalExpenses: Double = 0
typealias returnCalc = (Double) -> Void
func getIncData(completion: @escaping returnCalc) {
let budgetDB = Database.database().reference().child("Income")
budgetDB.observe(.childAdded) { (snapshot) in
let snapshotValue = snapshot.value as! Dictionary<String, String>
let value = snapshotValue["Value"]!
self.income.append(Double(Int(value)!))
// self.totalIncome = self.income.reduce(0, +)
self.incomeLabel.text = "Income: " + String(self.income.reduce(0, +)) + " €";
completion(self.income.reduce(0, +))
}
}
func getExpData(completion: @escaping returnCalc) {
let budgetDB = Database.database().reference().child("Expenses")
budgetDB.observe(.childAdded) { (snapshot) in
let snapshotValue = snapshot.value as! Dictionary<String, String>
let value = snapshotValue["Value"]!
self.expenses.append(Double(value)!)
// self.totalExpenses = self.expenses.reduce(0, +)
self.expensesLabel.text = "Expenses: " + String(Double(self.expenses.reduce(0, +))) + " €";
completion(self.expenses.reduce(0, +))
}
}
func getLeftBudget() {
getIncData { (inc) in
getExpData(completion: { (exp) in
let budgetLeft = inc - exp
self.budgetMonth.text = "Budget left - \(String(budgetLeft))"
})
}
}
Upvotes: 1