0

I'm trying to get data from my database and after obtaining a piece of data, using that piece of data to find a new piece of data.

At the end, I can piece these together and return the derived data. I'm not sure this is the best way to approach this, but this is where im at as of now.

My problem is that each call to the database (Firebase) is async and therefore I need to somehow wait for the async to finish, before going on.

I've looked at dispatch group and heres what I have so far:

 let taskGroup = DispatchGroup()

    for buildingKey in building.allKeys
    {
      var aprt = NSDictionary()

      taskGroup.enter()
         // ASYNC REQUEST
      getAbodesWithUID(UID: buildingKey as! String, callback: { (success, abodes) in
        aprt = abodes
        taskGroup.leave()
      })

      taskGroup.enter()
      for key in aprt.allKeys
      {
        // ASYNC REQUEST
        getTenantsWithAprt(UID: key as! String, callback: { (success, user) in
          for userKey in user.allKeys
          {
            let dict = NSMutableDictionary()
            dict.setValue(((building[buildingKey] as? NSDictionary)?["Address"] as? NSDictionary)?.allKeys[0] as? String, forKey: "Building")
            dict.setValue((user[userKey] as? NSDictionary)?["Aprt"], forKey: "Number")
            dict.setValue((user[userKey] as? NSDictionary)?["Name"], forKey: "Name")
            dict.setValue(userKey, forKey: "UID")
            dict.setValue((user[userKey] as? NSDictionary)?["PhoneNumber"], forKey: "Phone")
            apartments.append(dict)
          }
          taskGroup.leave()
        })
      }
    }

    taskGroup.notify(queue: DispatchQueue.main, execute: {
      print("DONE")
      callback(true, apartments)
    })

I can't seem to get it to callback properly

4
  • I would use completion handlers for this. Commented Mar 19, 2018 at 1:02
  • @Jake Can you explain a bit furthur? Isnt callback a completion handler? Commented Mar 19, 2018 at 1:03
  • Yes it is. If you're trying to get a value, then find a new result using the value you just got, I would try to write a function with a completion handler, and nest your function within it's own completion handler to get your data one tier at a time. function( completion { if true { function(completion etc., )} )} Commented Mar 19, 2018 at 1:06
  • @Jake But its all in a for loop. So where would i put the main functions completion handler? If its outside the nested part, the nested part is async so the main completion handler will be called before they finish and if its inside, it will get called once, the first time Commented Mar 19, 2018 at 1:08

2 Answers 2

1

First, you should be iterating over aprt.allKeys inside of the callback for getAbodesWithUID, other wise, when the for loop executes aprt will be an empty dictionary.

Secondly, the taskGroup.enter() call above that for loop should be inside of the for loop, because it needs to be called once for every key. It should be placed where the // ASYNC REQUEST comment currently is.

Sign up to request clarification or add additional context in comments.

Comments

0

This is precisely what "promises" are for is for. They are available in Swift via a 3rd party add-in. A popular way to do this is to push all your reads/gets into an array. Then you promise.all(yourArray) which returns the array of results/values that you then iterate over to get at each one.

From this other answer:

You can look into when which may provide what you need and is covered here.

Use the loop to put your promises into an array and then do something like this:

when(fulfilled: promiseArray).then { results in
    // Do something
}.catch { error in
    // Handle error
}

1 Comment

Swift does NOT have promises. You have to use a Swift 3rd party SDK for them. Please edit your answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.