Two functions that get data from a FireBase database, and a third function that performs some calulations





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















I have two functions that successfully retrieve integers from Firebase. I'd like a third function that does some simple subtraction from the integers gathered in the first two functions.



However, I'm very new to this, so can't get it to work correctly.



The output of the two functions that gather data from Firebase are:



let pointsRedeemedAsInt:Int = Int(Points_Redeem)!


and



let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}


What I'd like is a third function that looks like this:



let pointsBalance = sumOfPointsCompleted - pointsRedeemedAsInt


However, the third function doesn't recognise sumOfPointsCompleted, nor pointsRedeemedAsInt.



// First Function:



 func loadPointsRedeemed() {


databaseReference = Database.database().reference()

let userID = Auth.auth().currentUser?.uid

databaseReference.child("Users").child(userID!).observe(DataEventType.value, with: { (snapshot) in

let value = snapshot.value as? NSDictionary

// let Points_Earn = value?["Points_Earned"] as? String ?? ""
let Points_Redeem = value?["Points_Redeemed"] as? String ?? ""


// self.Points_Earned.text = Points_Earn
self.Points_Redeemed.text = Points_Redeem

let pointsRedeemedAsInt:Int = Int(Points_Redeem)!

// Do any additional setup after loading the view.
}

)}


//Second Function:



func LoadPointsCompleted() {

self.challengeList.removeAll()

databaseReference = Database.database().reference()

let userID = Auth.auth().currentUser?.uid

let refChallenges = Database.database().reference(withPath: "Challenges").child(userID!).queryOrdered(byChild: "Status").queryEqual(toValue: "Complete")

refChallenges.observeSingleEvent(of: .value, with: { (snapshot) in

//if the reference have some values
if snapshot.childrenCount > 0 {

//clearing the list
self.challengeList.removeAll()

//iterating through all the values
for Challenges in snapshot.children.allObjects as! [DataSnapshot] {
//getting values
let challengeObject = Challenges.value as? [String: AnyObject]
let Points = challengeObject?["Points"] as! Int

//creating challenge object with model and fetched values
let challenge = pointsModel(Points: (Points as Int?)!)

//appending it to list
self.challengeList.append(challenge)

let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}

let sumOfPointsCompletedString = String(sumOfPointsCompleted)
self.Calc_Earned.text = sumOfPointsCompletedString
}
}
}
)}


// Third Function (which does not work):



 func BalanceOfPoints(){

let balance = sum - pointsRedeemedAsInt

}


The error is:




Use of unresolved identifiers sum and pointsRedeemedAsInt




Furthermore, how do I ensure that everything is executed in the right order? ie, the loadPointsCompleted function must run (and complete) first, followed by the loadPointsRedeemed function, and finally the BalanceOfPoints function.










share|improve this question




















  • 1





    You are trying to access variables that are outside of the scope of the method. That cannot be done. Try to read the swift docs before continuing so you have a better idea of how to do it.

    – Galo Torres Sevilla
    Jan 4 at 0:53


















1















I have two functions that successfully retrieve integers from Firebase. I'd like a third function that does some simple subtraction from the integers gathered in the first two functions.



However, I'm very new to this, so can't get it to work correctly.



The output of the two functions that gather data from Firebase are:



let pointsRedeemedAsInt:Int = Int(Points_Redeem)!


and



let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}


What I'd like is a third function that looks like this:



let pointsBalance = sumOfPointsCompleted - pointsRedeemedAsInt


However, the third function doesn't recognise sumOfPointsCompleted, nor pointsRedeemedAsInt.



// First Function:



 func loadPointsRedeemed() {


databaseReference = Database.database().reference()

let userID = Auth.auth().currentUser?.uid

databaseReference.child("Users").child(userID!).observe(DataEventType.value, with: { (snapshot) in

let value = snapshot.value as? NSDictionary

// let Points_Earn = value?["Points_Earned"] as? String ?? ""
let Points_Redeem = value?["Points_Redeemed"] as? String ?? ""


// self.Points_Earned.text = Points_Earn
self.Points_Redeemed.text = Points_Redeem

let pointsRedeemedAsInt:Int = Int(Points_Redeem)!

// Do any additional setup after loading the view.
}

)}


//Second Function:



func LoadPointsCompleted() {

self.challengeList.removeAll()

databaseReference = Database.database().reference()

let userID = Auth.auth().currentUser?.uid

let refChallenges = Database.database().reference(withPath: "Challenges").child(userID!).queryOrdered(byChild: "Status").queryEqual(toValue: "Complete")

refChallenges.observeSingleEvent(of: .value, with: { (snapshot) in

//if the reference have some values
if snapshot.childrenCount > 0 {

//clearing the list
self.challengeList.removeAll()

//iterating through all the values
for Challenges in snapshot.children.allObjects as! [DataSnapshot] {
//getting values
let challengeObject = Challenges.value as? [String: AnyObject]
let Points = challengeObject?["Points"] as! Int

//creating challenge object with model and fetched values
let challenge = pointsModel(Points: (Points as Int?)!)

//appending it to list
self.challengeList.append(challenge)

let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}

let sumOfPointsCompletedString = String(sumOfPointsCompleted)
self.Calc_Earned.text = sumOfPointsCompletedString
}
}
}
)}


// Third Function (which does not work):



 func BalanceOfPoints(){

let balance = sum - pointsRedeemedAsInt

}


The error is:




Use of unresolved identifiers sum and pointsRedeemedAsInt




Furthermore, how do I ensure that everything is executed in the right order? ie, the loadPointsCompleted function must run (and complete) first, followed by the loadPointsRedeemed function, and finally the BalanceOfPoints function.










share|improve this question




















  • 1





    You are trying to access variables that are outside of the scope of the method. That cannot be done. Try to read the swift docs before continuing so you have a better idea of how to do it.

    – Galo Torres Sevilla
    Jan 4 at 0:53














1












1








1








I have two functions that successfully retrieve integers from Firebase. I'd like a third function that does some simple subtraction from the integers gathered in the first two functions.



However, I'm very new to this, so can't get it to work correctly.



The output of the two functions that gather data from Firebase are:



let pointsRedeemedAsInt:Int = Int(Points_Redeem)!


and



let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}


What I'd like is a third function that looks like this:



let pointsBalance = sumOfPointsCompleted - pointsRedeemedAsInt


However, the third function doesn't recognise sumOfPointsCompleted, nor pointsRedeemedAsInt.



// First Function:



 func loadPointsRedeemed() {


databaseReference = Database.database().reference()

let userID = Auth.auth().currentUser?.uid

databaseReference.child("Users").child(userID!).observe(DataEventType.value, with: { (snapshot) in

let value = snapshot.value as? NSDictionary

// let Points_Earn = value?["Points_Earned"] as? String ?? ""
let Points_Redeem = value?["Points_Redeemed"] as? String ?? ""


// self.Points_Earned.text = Points_Earn
self.Points_Redeemed.text = Points_Redeem

let pointsRedeemedAsInt:Int = Int(Points_Redeem)!

// Do any additional setup after loading the view.
}

)}


//Second Function:



func LoadPointsCompleted() {

self.challengeList.removeAll()

databaseReference = Database.database().reference()

let userID = Auth.auth().currentUser?.uid

let refChallenges = Database.database().reference(withPath: "Challenges").child(userID!).queryOrdered(byChild: "Status").queryEqual(toValue: "Complete")

refChallenges.observeSingleEvent(of: .value, with: { (snapshot) in

//if the reference have some values
if snapshot.childrenCount > 0 {

//clearing the list
self.challengeList.removeAll()

//iterating through all the values
for Challenges in snapshot.children.allObjects as! [DataSnapshot] {
//getting values
let challengeObject = Challenges.value as? [String: AnyObject]
let Points = challengeObject?["Points"] as! Int

//creating challenge object with model and fetched values
let challenge = pointsModel(Points: (Points as Int?)!)

//appending it to list
self.challengeList.append(challenge)

let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}

let sumOfPointsCompletedString = String(sumOfPointsCompleted)
self.Calc_Earned.text = sumOfPointsCompletedString
}
}
}
)}


// Third Function (which does not work):



 func BalanceOfPoints(){

let balance = sum - pointsRedeemedAsInt

}


The error is:




Use of unresolved identifiers sum and pointsRedeemedAsInt




Furthermore, how do I ensure that everything is executed in the right order? ie, the loadPointsCompleted function must run (and complete) first, followed by the loadPointsRedeemed function, and finally the BalanceOfPoints function.










share|improve this question
















I have two functions that successfully retrieve integers from Firebase. I'd like a third function that does some simple subtraction from the integers gathered in the first two functions.



However, I'm very new to this, so can't get it to work correctly.



The output of the two functions that gather data from Firebase are:



let pointsRedeemedAsInt:Int = Int(Points_Redeem)!


and



let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}


What I'd like is a third function that looks like this:



let pointsBalance = sumOfPointsCompleted - pointsRedeemedAsInt


However, the third function doesn't recognise sumOfPointsCompleted, nor pointsRedeemedAsInt.



// First Function:



 func loadPointsRedeemed() {


databaseReference = Database.database().reference()

let userID = Auth.auth().currentUser?.uid

databaseReference.child("Users").child(userID!).observe(DataEventType.value, with: { (snapshot) in

let value = snapshot.value as? NSDictionary

// let Points_Earn = value?["Points_Earned"] as? String ?? ""
let Points_Redeem = value?["Points_Redeemed"] as? String ?? ""


// self.Points_Earned.text = Points_Earn
self.Points_Redeemed.text = Points_Redeem

let pointsRedeemedAsInt:Int = Int(Points_Redeem)!

// Do any additional setup after loading the view.
}

)}


//Second Function:



func LoadPointsCompleted() {

self.challengeList.removeAll()

databaseReference = Database.database().reference()

let userID = Auth.auth().currentUser?.uid

let refChallenges = Database.database().reference(withPath: "Challenges").child(userID!).queryOrdered(byChild: "Status").queryEqual(toValue: "Complete")

refChallenges.observeSingleEvent(of: .value, with: { (snapshot) in

//if the reference have some values
if snapshot.childrenCount > 0 {

//clearing the list
self.challengeList.removeAll()

//iterating through all the values
for Challenges in snapshot.children.allObjects as! [DataSnapshot] {
//getting values
let challengeObject = Challenges.value as? [String: AnyObject]
let Points = challengeObject?["Points"] as! Int

//creating challenge object with model and fetched values
let challenge = pointsModel(Points: (Points as Int?)!)

//appending it to list
self.challengeList.append(challenge)

let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}

let sumOfPointsCompletedString = String(sumOfPointsCompleted)
self.Calc_Earned.text = sumOfPointsCompletedString
}
}
}
)}


// Third Function (which does not work):



 func BalanceOfPoints(){

let balance = sum - pointsRedeemedAsInt

}


The error is:




Use of unresolved identifiers sum and pointsRedeemedAsInt




Furthermore, how do I ensure that everything is executed in the right order? ie, the loadPointsCompleted function must run (and complete) first, followed by the loadPointsRedeemed function, and finally the BalanceOfPoints function.







ios swift firebase firebase-realtime-database






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 4 at 0:47









Frank van Puffelen

245k31390419




245k31390419










asked Jan 4 at 0:46









nm1213nm1213

448




448








  • 1





    You are trying to access variables that are outside of the scope of the method. That cannot be done. Try to read the swift docs before continuing so you have a better idea of how to do it.

    – Galo Torres Sevilla
    Jan 4 at 0:53














  • 1





    You are trying to access variables that are outside of the scope of the method. That cannot be done. Try to read the swift docs before continuing so you have a better idea of how to do it.

    – Galo Torres Sevilla
    Jan 4 at 0:53








1




1





You are trying to access variables that are outside of the scope of the method. That cannot be done. Try to read the swift docs before continuing so you have a better idea of how to do it.

– Galo Torres Sevilla
Jan 4 at 0:53





You are trying to access variables that are outside of the scope of the method. That cannot be done. Try to read the swift docs before continuing so you have a better idea of how to do it.

– Galo Torres Sevilla
Jan 4 at 0:53












2 Answers
2






active

oldest

votes


















1














Actually, the problem is that you are not considering that retrieving data from remote sources is asynchronous.
This means that you have to wait for data to be retrieved before calling the other functions.



To achieve this result, you should use swift closure (callback in other languages) with completion handler. Check this documentation.



Change your functions this way:



First Function



func loadPointsRedeemed(completion: @escaping (_:Int)->()){

databaseReference = Database.database().reference()

let userID = Auth.auth().currentUser?.uid

databaseReference.child("Users").child(userID!).observe(DataEventType.value, with: { (snapshot) in

let value = snapshot.value as? NSDictionary

// let Points_Earn = value?["Points_Earned"] as? String ?? ""
let Points_Redeem = value?["Points_Redeemed"] as? String ?? ""


// self.Points_Earned.text = Points_Earn
self.Points_Redeemed.text = Points_Redeem

let pointsRedeemedAsInt:Int = Int(Points_Redeem)!

// Do any additional setup after loading the view.

//Call your return back function called "completion"
completion(pointsRedeemedAsInt)

}

)}


Second Function



func loadPointsCompleted(completion: @escaping (_:Int)->()){

self.challengeList.removeAll()

databaseReference = Database.database().reference()

let userID = Auth.auth().currentUser?.uid

let refChallenges = Database.database().reference(withPath: "Challenges").child(userID!).queryOrdered(byChild: "Status").queryEqual(toValue: "Complete")

refChallenges.observeSingleEvent(of: .value, with: { (snapshot) in

//if the reference have some values
if snapshot.childrenCount > 0 {

//clearing the list
self.challengeList.removeAll()

//iterating through all the values
for Challenges in snapshot.children.allObjects as! [DataSnapshot] {
//getting values
let challengeObject = Challenges.value as? [String: AnyObject]
let Points = challengeObject?["Points"] as! Int

//creating challenge object with model and fetched values
let challenge = pointsModel(Points: (Points as Int?)!)

//appending it to list
self.challengeList.append(challenge)

}

let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}

let sumOfPointsCompletedString = String(sumOfPointsCompleted)
self.Calc_Earned.text = sumOfPointsCompletedString

completion(sumOfPointsCompleted)

}
}
)}


Third Function



 func balanceOfPoints(completion: @escaping (_:Int)->()) {
loadPointsCompleted{(sum) in
//HERE YOU CAN USE THE RESULT OF loadPointsCompleted
//I CALLED IT sum

loadPointsRedeemed{ (pointsRedeemedAsInt) in
// HERE YOU CAN USE THE RESULT OF loadPointsRedeemed
//I CALLED IT pointsRedeemedAsInt
let balance = sum - pointsRedeemedAsInt
completion(balance)
}
}

}


To call the balance function wherever you want:



       balanceOfPoints{ (balance) in
// Whatever you want with balance
}


If you change the view ( for example you set some label text ), be sure to use the functions in the main thread.






share|improve this answer































    0














    The problem is that you are trying to access variables outside the scope of BalanceOfPoints().



    Try returning the values you want to use in the equation from the first two functions, loadPointsRedeemed() and LoadPointsCompleted(). This can be done like so:



    First Function



    func loadPointsRedeemed() -> Int {

    databaseReference = Database.database().reference()

    let userID = Auth.auth().currentUser?.uid

    databaseReference.child("Users").child(userID!).observe(DataEventType.value, with: { (snapshot) in

    let value = snapshot.value as? NSDictionary

    // let Points_Earn = value?["Points_Earned"] as? String ?? ""
    let Points_Redeem = value?["Points_Redeemed"] as? String ?? ""


    // self.Points_Earned.text = Points_Earn
    self.Points_Redeemed.text = Points_Redeem

    let pointsRedeemedAsInt:Int = Int(Points_Redeem)!

    // Do any additional setup after loading the view.

    return pointsRedeemedAsInt

    }

    )}


    Second Function



    func loadPointsCompleted() -> Int {

    self.challengeList.removeAll()

    databaseReference = Database.database().reference()

    let userID = Auth.auth().currentUser?.uid

    let refChallenges = Database.database().reference(withPath: "Challenges").child(userID!).queryOrdered(byChild: "Status").queryEqual(toValue: "Complete")

    refChallenges.observeSingleEvent(of: .value, with: { (snapshot) in

    //if the reference have some values
    if snapshot.childrenCount > 0 {

    //clearing the list
    self.challengeList.removeAll()

    //iterating through all the values
    for Challenges in snapshot.children.allObjects as! [DataSnapshot] {
    //getting values
    let challengeObject = Challenges.value as? [String: AnyObject]
    let Points = challengeObject?["Points"] as! Int

    //creating challenge object with model and fetched values
    let challenge = pointsModel(Points: (Points as Int?)!)

    //appending it to list
    self.challengeList.append(challenge)

    }

    let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}

    let sumOfPointsCompletedString = String(sumOfPointsCompleted)
    self.Calc_Earned.text = sumOfPointsCompletedString

    return sumOfPointsCompleted

    }
    }
    )}


    Third Function



    func balanceOfPoints() -> Int {

    let sum = loadPointsCompleted()
    let pointsRedeemedAsInt = loadPointsRedeemed()

    let balance = sum - pointsRedeemedAsInt

    return balance

    }


    Now, wherever you call the functions loadPointsRedeemed() and loadPointsCompleted(), replace these calls with balanceOfPoints.



    Notice the main changes I made to your code are adding return values to your functions so they can be used in other areas of your code. Check out the Swift Functions Documentation to learn more.






    share|improve this answer
























    • Thanks Mathyou, tried this but now get the following error: Unexpected non-void return value in void function.

      – nm1213
      Jan 4 at 4:27











    • @nm1213 You're missing the return type in the declaration of each function. Look at the samples I wrote again. At the end of each function, between the () and {, I have a ` -> Int`. This means the function must return an integer. Not having this means the function expects a void return value, in other words, none at all.

      – Mathyou
      Jan 4 at 14:17












    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54031789%2ftwo-functions-that-get-data-from-a-firebase-database-and-a-third-function-that%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    Actually, the problem is that you are not considering that retrieving data from remote sources is asynchronous.
    This means that you have to wait for data to be retrieved before calling the other functions.



    To achieve this result, you should use swift closure (callback in other languages) with completion handler. Check this documentation.



    Change your functions this way:



    First Function



    func loadPointsRedeemed(completion: @escaping (_:Int)->()){

    databaseReference = Database.database().reference()

    let userID = Auth.auth().currentUser?.uid

    databaseReference.child("Users").child(userID!).observe(DataEventType.value, with: { (snapshot) in

    let value = snapshot.value as? NSDictionary

    // let Points_Earn = value?["Points_Earned"] as? String ?? ""
    let Points_Redeem = value?["Points_Redeemed"] as? String ?? ""


    // self.Points_Earned.text = Points_Earn
    self.Points_Redeemed.text = Points_Redeem

    let pointsRedeemedAsInt:Int = Int(Points_Redeem)!

    // Do any additional setup after loading the view.

    //Call your return back function called "completion"
    completion(pointsRedeemedAsInt)

    }

    )}


    Second Function



    func loadPointsCompleted(completion: @escaping (_:Int)->()){

    self.challengeList.removeAll()

    databaseReference = Database.database().reference()

    let userID = Auth.auth().currentUser?.uid

    let refChallenges = Database.database().reference(withPath: "Challenges").child(userID!).queryOrdered(byChild: "Status").queryEqual(toValue: "Complete")

    refChallenges.observeSingleEvent(of: .value, with: { (snapshot) in

    //if the reference have some values
    if snapshot.childrenCount > 0 {

    //clearing the list
    self.challengeList.removeAll()

    //iterating through all the values
    for Challenges in snapshot.children.allObjects as! [DataSnapshot] {
    //getting values
    let challengeObject = Challenges.value as? [String: AnyObject]
    let Points = challengeObject?["Points"] as! Int

    //creating challenge object with model and fetched values
    let challenge = pointsModel(Points: (Points as Int?)!)

    //appending it to list
    self.challengeList.append(challenge)

    }

    let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}

    let sumOfPointsCompletedString = String(sumOfPointsCompleted)
    self.Calc_Earned.text = sumOfPointsCompletedString

    completion(sumOfPointsCompleted)

    }
    }
    )}


    Third Function



     func balanceOfPoints(completion: @escaping (_:Int)->()) {
    loadPointsCompleted{(sum) in
    //HERE YOU CAN USE THE RESULT OF loadPointsCompleted
    //I CALLED IT sum

    loadPointsRedeemed{ (pointsRedeemedAsInt) in
    // HERE YOU CAN USE THE RESULT OF loadPointsRedeemed
    //I CALLED IT pointsRedeemedAsInt
    let balance = sum - pointsRedeemedAsInt
    completion(balance)
    }
    }

    }


    To call the balance function wherever you want:



           balanceOfPoints{ (balance) in
    // Whatever you want with balance
    }


    If you change the view ( for example you set some label text ), be sure to use the functions in the main thread.






    share|improve this answer




























      1














      Actually, the problem is that you are not considering that retrieving data from remote sources is asynchronous.
      This means that you have to wait for data to be retrieved before calling the other functions.



      To achieve this result, you should use swift closure (callback in other languages) with completion handler. Check this documentation.



      Change your functions this way:



      First Function



      func loadPointsRedeemed(completion: @escaping (_:Int)->()){

      databaseReference = Database.database().reference()

      let userID = Auth.auth().currentUser?.uid

      databaseReference.child("Users").child(userID!).observe(DataEventType.value, with: { (snapshot) in

      let value = snapshot.value as? NSDictionary

      // let Points_Earn = value?["Points_Earned"] as? String ?? ""
      let Points_Redeem = value?["Points_Redeemed"] as? String ?? ""


      // self.Points_Earned.text = Points_Earn
      self.Points_Redeemed.text = Points_Redeem

      let pointsRedeemedAsInt:Int = Int(Points_Redeem)!

      // Do any additional setup after loading the view.

      //Call your return back function called "completion"
      completion(pointsRedeemedAsInt)

      }

      )}


      Second Function



      func loadPointsCompleted(completion: @escaping (_:Int)->()){

      self.challengeList.removeAll()

      databaseReference = Database.database().reference()

      let userID = Auth.auth().currentUser?.uid

      let refChallenges = Database.database().reference(withPath: "Challenges").child(userID!).queryOrdered(byChild: "Status").queryEqual(toValue: "Complete")

      refChallenges.observeSingleEvent(of: .value, with: { (snapshot) in

      //if the reference have some values
      if snapshot.childrenCount > 0 {

      //clearing the list
      self.challengeList.removeAll()

      //iterating through all the values
      for Challenges in snapshot.children.allObjects as! [DataSnapshot] {
      //getting values
      let challengeObject = Challenges.value as? [String: AnyObject]
      let Points = challengeObject?["Points"] as! Int

      //creating challenge object with model and fetched values
      let challenge = pointsModel(Points: (Points as Int?)!)

      //appending it to list
      self.challengeList.append(challenge)

      }

      let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}

      let sumOfPointsCompletedString = String(sumOfPointsCompleted)
      self.Calc_Earned.text = sumOfPointsCompletedString

      completion(sumOfPointsCompleted)

      }
      }
      )}


      Third Function



       func balanceOfPoints(completion: @escaping (_:Int)->()) {
      loadPointsCompleted{(sum) in
      //HERE YOU CAN USE THE RESULT OF loadPointsCompleted
      //I CALLED IT sum

      loadPointsRedeemed{ (pointsRedeemedAsInt) in
      // HERE YOU CAN USE THE RESULT OF loadPointsRedeemed
      //I CALLED IT pointsRedeemedAsInt
      let balance = sum - pointsRedeemedAsInt
      completion(balance)
      }
      }

      }


      To call the balance function wherever you want:



             balanceOfPoints{ (balance) in
      // Whatever you want with balance
      }


      If you change the view ( for example you set some label text ), be sure to use the functions in the main thread.






      share|improve this answer


























        1












        1








        1







        Actually, the problem is that you are not considering that retrieving data from remote sources is asynchronous.
        This means that you have to wait for data to be retrieved before calling the other functions.



        To achieve this result, you should use swift closure (callback in other languages) with completion handler. Check this documentation.



        Change your functions this way:



        First Function



        func loadPointsRedeemed(completion: @escaping (_:Int)->()){

        databaseReference = Database.database().reference()

        let userID = Auth.auth().currentUser?.uid

        databaseReference.child("Users").child(userID!).observe(DataEventType.value, with: { (snapshot) in

        let value = snapshot.value as? NSDictionary

        // let Points_Earn = value?["Points_Earned"] as? String ?? ""
        let Points_Redeem = value?["Points_Redeemed"] as? String ?? ""


        // self.Points_Earned.text = Points_Earn
        self.Points_Redeemed.text = Points_Redeem

        let pointsRedeemedAsInt:Int = Int(Points_Redeem)!

        // Do any additional setup after loading the view.

        //Call your return back function called "completion"
        completion(pointsRedeemedAsInt)

        }

        )}


        Second Function



        func loadPointsCompleted(completion: @escaping (_:Int)->()){

        self.challengeList.removeAll()

        databaseReference = Database.database().reference()

        let userID = Auth.auth().currentUser?.uid

        let refChallenges = Database.database().reference(withPath: "Challenges").child(userID!).queryOrdered(byChild: "Status").queryEqual(toValue: "Complete")

        refChallenges.observeSingleEvent(of: .value, with: { (snapshot) in

        //if the reference have some values
        if snapshot.childrenCount > 0 {

        //clearing the list
        self.challengeList.removeAll()

        //iterating through all the values
        for Challenges in snapshot.children.allObjects as! [DataSnapshot] {
        //getting values
        let challengeObject = Challenges.value as? [String: AnyObject]
        let Points = challengeObject?["Points"] as! Int

        //creating challenge object with model and fetched values
        let challenge = pointsModel(Points: (Points as Int?)!)

        //appending it to list
        self.challengeList.append(challenge)

        }

        let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}

        let sumOfPointsCompletedString = String(sumOfPointsCompleted)
        self.Calc_Earned.text = sumOfPointsCompletedString

        completion(sumOfPointsCompleted)

        }
        }
        )}


        Third Function



         func balanceOfPoints(completion: @escaping (_:Int)->()) {
        loadPointsCompleted{(sum) in
        //HERE YOU CAN USE THE RESULT OF loadPointsCompleted
        //I CALLED IT sum

        loadPointsRedeemed{ (pointsRedeemedAsInt) in
        // HERE YOU CAN USE THE RESULT OF loadPointsRedeemed
        //I CALLED IT pointsRedeemedAsInt
        let balance = sum - pointsRedeemedAsInt
        completion(balance)
        }
        }

        }


        To call the balance function wherever you want:



               balanceOfPoints{ (balance) in
        // Whatever you want with balance
        }


        If you change the view ( for example you set some label text ), be sure to use the functions in the main thread.






        share|improve this answer













        Actually, the problem is that you are not considering that retrieving data from remote sources is asynchronous.
        This means that you have to wait for data to be retrieved before calling the other functions.



        To achieve this result, you should use swift closure (callback in other languages) with completion handler. Check this documentation.



        Change your functions this way:



        First Function



        func loadPointsRedeemed(completion: @escaping (_:Int)->()){

        databaseReference = Database.database().reference()

        let userID = Auth.auth().currentUser?.uid

        databaseReference.child("Users").child(userID!).observe(DataEventType.value, with: { (snapshot) in

        let value = snapshot.value as? NSDictionary

        // let Points_Earn = value?["Points_Earned"] as? String ?? ""
        let Points_Redeem = value?["Points_Redeemed"] as? String ?? ""


        // self.Points_Earned.text = Points_Earn
        self.Points_Redeemed.text = Points_Redeem

        let pointsRedeemedAsInt:Int = Int(Points_Redeem)!

        // Do any additional setup after loading the view.

        //Call your return back function called "completion"
        completion(pointsRedeemedAsInt)

        }

        )}


        Second Function



        func loadPointsCompleted(completion: @escaping (_:Int)->()){

        self.challengeList.removeAll()

        databaseReference = Database.database().reference()

        let userID = Auth.auth().currentUser?.uid

        let refChallenges = Database.database().reference(withPath: "Challenges").child(userID!).queryOrdered(byChild: "Status").queryEqual(toValue: "Complete")

        refChallenges.observeSingleEvent(of: .value, with: { (snapshot) in

        //if the reference have some values
        if snapshot.childrenCount > 0 {

        //clearing the list
        self.challengeList.removeAll()

        //iterating through all the values
        for Challenges in snapshot.children.allObjects as! [DataSnapshot] {
        //getting values
        let challengeObject = Challenges.value as? [String: AnyObject]
        let Points = challengeObject?["Points"] as! Int

        //creating challenge object with model and fetched values
        let challenge = pointsModel(Points: (Points as Int?)!)

        //appending it to list
        self.challengeList.append(challenge)

        }

        let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}

        let sumOfPointsCompletedString = String(sumOfPointsCompleted)
        self.Calc_Earned.text = sumOfPointsCompletedString

        completion(sumOfPointsCompleted)

        }
        }
        )}


        Third Function



         func balanceOfPoints(completion: @escaping (_:Int)->()) {
        loadPointsCompleted{(sum) in
        //HERE YOU CAN USE THE RESULT OF loadPointsCompleted
        //I CALLED IT sum

        loadPointsRedeemed{ (pointsRedeemedAsInt) in
        // HERE YOU CAN USE THE RESULT OF loadPointsRedeemed
        //I CALLED IT pointsRedeemedAsInt
        let balance = sum - pointsRedeemedAsInt
        completion(balance)
        }
        }

        }


        To call the balance function wherever you want:



               balanceOfPoints{ (balance) in
        // Whatever you want with balance
        }


        If you change the view ( for example you set some label text ), be sure to use the functions in the main thread.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 31 at 16:34









        Andrew21111Andrew21111

        524414




        524414

























            0














            The problem is that you are trying to access variables outside the scope of BalanceOfPoints().



            Try returning the values you want to use in the equation from the first two functions, loadPointsRedeemed() and LoadPointsCompleted(). This can be done like so:



            First Function



            func loadPointsRedeemed() -> Int {

            databaseReference = Database.database().reference()

            let userID = Auth.auth().currentUser?.uid

            databaseReference.child("Users").child(userID!).observe(DataEventType.value, with: { (snapshot) in

            let value = snapshot.value as? NSDictionary

            // let Points_Earn = value?["Points_Earned"] as? String ?? ""
            let Points_Redeem = value?["Points_Redeemed"] as? String ?? ""


            // self.Points_Earned.text = Points_Earn
            self.Points_Redeemed.text = Points_Redeem

            let pointsRedeemedAsInt:Int = Int(Points_Redeem)!

            // Do any additional setup after loading the view.

            return pointsRedeemedAsInt

            }

            )}


            Second Function



            func loadPointsCompleted() -> Int {

            self.challengeList.removeAll()

            databaseReference = Database.database().reference()

            let userID = Auth.auth().currentUser?.uid

            let refChallenges = Database.database().reference(withPath: "Challenges").child(userID!).queryOrdered(byChild: "Status").queryEqual(toValue: "Complete")

            refChallenges.observeSingleEvent(of: .value, with: { (snapshot) in

            //if the reference have some values
            if snapshot.childrenCount > 0 {

            //clearing the list
            self.challengeList.removeAll()

            //iterating through all the values
            for Challenges in snapshot.children.allObjects as! [DataSnapshot] {
            //getting values
            let challengeObject = Challenges.value as? [String: AnyObject]
            let Points = challengeObject?["Points"] as! Int

            //creating challenge object with model and fetched values
            let challenge = pointsModel(Points: (Points as Int?)!)

            //appending it to list
            self.challengeList.append(challenge)

            }

            let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}

            let sumOfPointsCompletedString = String(sumOfPointsCompleted)
            self.Calc_Earned.text = sumOfPointsCompletedString

            return sumOfPointsCompleted

            }
            }
            )}


            Third Function



            func balanceOfPoints() -> Int {

            let sum = loadPointsCompleted()
            let pointsRedeemedAsInt = loadPointsRedeemed()

            let balance = sum - pointsRedeemedAsInt

            return balance

            }


            Now, wherever you call the functions loadPointsRedeemed() and loadPointsCompleted(), replace these calls with balanceOfPoints.



            Notice the main changes I made to your code are adding return values to your functions so they can be used in other areas of your code. Check out the Swift Functions Documentation to learn more.






            share|improve this answer
























            • Thanks Mathyou, tried this but now get the following error: Unexpected non-void return value in void function.

              – nm1213
              Jan 4 at 4:27











            • @nm1213 You're missing the return type in the declaration of each function. Look at the samples I wrote again. At the end of each function, between the () and {, I have a ` -> Int`. This means the function must return an integer. Not having this means the function expects a void return value, in other words, none at all.

              – Mathyou
              Jan 4 at 14:17
















            0














            The problem is that you are trying to access variables outside the scope of BalanceOfPoints().



            Try returning the values you want to use in the equation from the first two functions, loadPointsRedeemed() and LoadPointsCompleted(). This can be done like so:



            First Function



            func loadPointsRedeemed() -> Int {

            databaseReference = Database.database().reference()

            let userID = Auth.auth().currentUser?.uid

            databaseReference.child("Users").child(userID!).observe(DataEventType.value, with: { (snapshot) in

            let value = snapshot.value as? NSDictionary

            // let Points_Earn = value?["Points_Earned"] as? String ?? ""
            let Points_Redeem = value?["Points_Redeemed"] as? String ?? ""


            // self.Points_Earned.text = Points_Earn
            self.Points_Redeemed.text = Points_Redeem

            let pointsRedeemedAsInt:Int = Int(Points_Redeem)!

            // Do any additional setup after loading the view.

            return pointsRedeemedAsInt

            }

            )}


            Second Function



            func loadPointsCompleted() -> Int {

            self.challengeList.removeAll()

            databaseReference = Database.database().reference()

            let userID = Auth.auth().currentUser?.uid

            let refChallenges = Database.database().reference(withPath: "Challenges").child(userID!).queryOrdered(byChild: "Status").queryEqual(toValue: "Complete")

            refChallenges.observeSingleEvent(of: .value, with: { (snapshot) in

            //if the reference have some values
            if snapshot.childrenCount > 0 {

            //clearing the list
            self.challengeList.removeAll()

            //iterating through all the values
            for Challenges in snapshot.children.allObjects as! [DataSnapshot] {
            //getting values
            let challengeObject = Challenges.value as? [String: AnyObject]
            let Points = challengeObject?["Points"] as! Int

            //creating challenge object with model and fetched values
            let challenge = pointsModel(Points: (Points as Int?)!)

            //appending it to list
            self.challengeList.append(challenge)

            }

            let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}

            let sumOfPointsCompletedString = String(sumOfPointsCompleted)
            self.Calc_Earned.text = sumOfPointsCompletedString

            return sumOfPointsCompleted

            }
            }
            )}


            Third Function



            func balanceOfPoints() -> Int {

            let sum = loadPointsCompleted()
            let pointsRedeemedAsInt = loadPointsRedeemed()

            let balance = sum - pointsRedeemedAsInt

            return balance

            }


            Now, wherever you call the functions loadPointsRedeemed() and loadPointsCompleted(), replace these calls with balanceOfPoints.



            Notice the main changes I made to your code are adding return values to your functions so they can be used in other areas of your code. Check out the Swift Functions Documentation to learn more.






            share|improve this answer
























            • Thanks Mathyou, tried this but now get the following error: Unexpected non-void return value in void function.

              – nm1213
              Jan 4 at 4:27











            • @nm1213 You're missing the return type in the declaration of each function. Look at the samples I wrote again. At the end of each function, between the () and {, I have a ` -> Int`. This means the function must return an integer. Not having this means the function expects a void return value, in other words, none at all.

              – Mathyou
              Jan 4 at 14:17














            0












            0








            0







            The problem is that you are trying to access variables outside the scope of BalanceOfPoints().



            Try returning the values you want to use in the equation from the first two functions, loadPointsRedeemed() and LoadPointsCompleted(). This can be done like so:



            First Function



            func loadPointsRedeemed() -> Int {

            databaseReference = Database.database().reference()

            let userID = Auth.auth().currentUser?.uid

            databaseReference.child("Users").child(userID!).observe(DataEventType.value, with: { (snapshot) in

            let value = snapshot.value as? NSDictionary

            // let Points_Earn = value?["Points_Earned"] as? String ?? ""
            let Points_Redeem = value?["Points_Redeemed"] as? String ?? ""


            // self.Points_Earned.text = Points_Earn
            self.Points_Redeemed.text = Points_Redeem

            let pointsRedeemedAsInt:Int = Int(Points_Redeem)!

            // Do any additional setup after loading the view.

            return pointsRedeemedAsInt

            }

            )}


            Second Function



            func loadPointsCompleted() -> Int {

            self.challengeList.removeAll()

            databaseReference = Database.database().reference()

            let userID = Auth.auth().currentUser?.uid

            let refChallenges = Database.database().reference(withPath: "Challenges").child(userID!).queryOrdered(byChild: "Status").queryEqual(toValue: "Complete")

            refChallenges.observeSingleEvent(of: .value, with: { (snapshot) in

            //if the reference have some values
            if snapshot.childrenCount > 0 {

            //clearing the list
            self.challengeList.removeAll()

            //iterating through all the values
            for Challenges in snapshot.children.allObjects as! [DataSnapshot] {
            //getting values
            let challengeObject = Challenges.value as? [String: AnyObject]
            let Points = challengeObject?["Points"] as! Int

            //creating challenge object with model and fetched values
            let challenge = pointsModel(Points: (Points as Int?)!)

            //appending it to list
            self.challengeList.append(challenge)

            }

            let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}

            let sumOfPointsCompletedString = String(sumOfPointsCompleted)
            self.Calc_Earned.text = sumOfPointsCompletedString

            return sumOfPointsCompleted

            }
            }
            )}


            Third Function



            func balanceOfPoints() -> Int {

            let sum = loadPointsCompleted()
            let pointsRedeemedAsInt = loadPointsRedeemed()

            let balance = sum - pointsRedeemedAsInt

            return balance

            }


            Now, wherever you call the functions loadPointsRedeemed() and loadPointsCompleted(), replace these calls with balanceOfPoints.



            Notice the main changes I made to your code are adding return values to your functions so they can be used in other areas of your code. Check out the Swift Functions Documentation to learn more.






            share|improve this answer













            The problem is that you are trying to access variables outside the scope of BalanceOfPoints().



            Try returning the values you want to use in the equation from the first two functions, loadPointsRedeemed() and LoadPointsCompleted(). This can be done like so:



            First Function



            func loadPointsRedeemed() -> Int {

            databaseReference = Database.database().reference()

            let userID = Auth.auth().currentUser?.uid

            databaseReference.child("Users").child(userID!).observe(DataEventType.value, with: { (snapshot) in

            let value = snapshot.value as? NSDictionary

            // let Points_Earn = value?["Points_Earned"] as? String ?? ""
            let Points_Redeem = value?["Points_Redeemed"] as? String ?? ""


            // self.Points_Earned.text = Points_Earn
            self.Points_Redeemed.text = Points_Redeem

            let pointsRedeemedAsInt:Int = Int(Points_Redeem)!

            // Do any additional setup after loading the view.

            return pointsRedeemedAsInt

            }

            )}


            Second Function



            func loadPointsCompleted() -> Int {

            self.challengeList.removeAll()

            databaseReference = Database.database().reference()

            let userID = Auth.auth().currentUser?.uid

            let refChallenges = Database.database().reference(withPath: "Challenges").child(userID!).queryOrdered(byChild: "Status").queryEqual(toValue: "Complete")

            refChallenges.observeSingleEvent(of: .value, with: { (snapshot) in

            //if the reference have some values
            if snapshot.childrenCount > 0 {

            //clearing the list
            self.challengeList.removeAll()

            //iterating through all the values
            for Challenges in snapshot.children.allObjects as! [DataSnapshot] {
            //getting values
            let challengeObject = Challenges.value as? [String: AnyObject]
            let Points = challengeObject?["Points"] as! Int

            //creating challenge object with model and fetched values
            let challenge = pointsModel(Points: (Points as Int?)!)

            //appending it to list
            self.challengeList.append(challenge)

            }

            let sumOfPointsCompleted = self.challengeList.reduce(0) {$0 + $1.Points}

            let sumOfPointsCompletedString = String(sumOfPointsCompleted)
            self.Calc_Earned.text = sumOfPointsCompletedString

            return sumOfPointsCompleted

            }
            }
            )}


            Third Function



            func balanceOfPoints() -> Int {

            let sum = loadPointsCompleted()
            let pointsRedeemedAsInt = loadPointsRedeemed()

            let balance = sum - pointsRedeemedAsInt

            return balance

            }


            Now, wherever you call the functions loadPointsRedeemed() and loadPointsCompleted(), replace these calls with balanceOfPoints.



            Notice the main changes I made to your code are adding return values to your functions so they can be used in other areas of your code. Check out the Swift Functions Documentation to learn more.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jan 4 at 4:03









            MathyouMathyou

            1411517




            1411517













            • Thanks Mathyou, tried this but now get the following error: Unexpected non-void return value in void function.

              – nm1213
              Jan 4 at 4:27











            • @nm1213 You're missing the return type in the declaration of each function. Look at the samples I wrote again. At the end of each function, between the () and {, I have a ` -> Int`. This means the function must return an integer. Not having this means the function expects a void return value, in other words, none at all.

              – Mathyou
              Jan 4 at 14:17



















            • Thanks Mathyou, tried this but now get the following error: Unexpected non-void return value in void function.

              – nm1213
              Jan 4 at 4:27











            • @nm1213 You're missing the return type in the declaration of each function. Look at the samples I wrote again. At the end of each function, between the () and {, I have a ` -> Int`. This means the function must return an integer. Not having this means the function expects a void return value, in other words, none at all.

              – Mathyou
              Jan 4 at 14:17

















            Thanks Mathyou, tried this but now get the following error: Unexpected non-void return value in void function.

            – nm1213
            Jan 4 at 4:27





            Thanks Mathyou, tried this but now get the following error: Unexpected non-void return value in void function.

            – nm1213
            Jan 4 at 4:27













            @nm1213 You're missing the return type in the declaration of each function. Look at the samples I wrote again. At the end of each function, between the () and {, I have a ` -> Int`. This means the function must return an integer. Not having this means the function expects a void return value, in other words, none at all.

            – Mathyou
            Jan 4 at 14:17





            @nm1213 You're missing the return type in the declaration of each function. Look at the samples I wrote again. At the end of each function, between the () and {, I have a ` -> Int`. This means the function must return an integer. Not having this means the function expects a void return value, in other words, none at all.

            – Mathyou
            Jan 4 at 14:17


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54031789%2ftwo-functions-that-get-data-from-a-firebase-database-and-a-third-function-that%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Monofisismo

            Angular Downloading a file using contenturl with Basic Authentication

            Olmecas