loliki
loliki

Reputation: 957

Swift pass data from a function to another

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

Answers (1)

GIJOW
GIJOW

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

Related Questions