Swift iOS rewrite a function that use Firebase database without updating a global variable I'm learning swift programming and i built a music trivia app for iOS that use firebase real time database.
I have a function that before the game start get the number of record for each category of the game and update a class variable that is a tuple called records.
var records = (classical: 0, mix: 0, casual: 0)

private func getNumberOfRecords(category: String)  {
    var ref: DatabaseReference!
    ref = Database.database().reference().child(category)
    ref.observeSingleEvent(of: .value) { snapshot in
        let enumerator = snapshot.children
        while((enumerator.nextObject() as? DataSnapshot) != nil) {
            switch category {
            case &quot;casual&quot;:
                records.casual += 1
               
            case &quot;classical&quot;:
                records.classical += 1
                
            case &quot;mix&quot;:
                records.mix += 1
                
            default: print(&quot;Error loading record from category \(category)&quot;)
            }
        }
    }
}

Here is how I call the function and because it's asynchronous the response I receive from firebase and I need to know the number of records before call another function that will load the game data from the database i use DispatchQueue and wait 3 seconds.
getNumberOfRecords(category: &quot;classical&quot;)
getNumberOfRecords(category: &quot;casual&quot;)
getNumberOfRecords(category: &quot;mix&quot;)
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
  loadDataFromDB(records: records.classical, category: &quot;classical&quot;)
  loadDataFromDB(records: records.casual, category: &quot;casual&quot;)
  loadDataFromDB(records: records.mix, category: &quot;mix&quot;)
}

Now this is working but it's pretty ugly, especially using the function getNumberOfRecords to update the global tuple records. I don't know how can I rewrite this because if i make getNumberOfRecords return a tuple rather than update the global one is always 0 when i pass it as parameter of the function loadDataFromDB inside the DispatchQueue.
Thanks in advance to anyone will have time to read this.
A typical way to write an asynchronous function is to have it take a function as an argument that will be called with the results when they are ready. Such a function is often called a completion handler.
private func getNumberOfRecords(category: String, completion: (Int) -&gt; Void) { 
   ...
            default: print(&quot;Error loading record from category \(category)&quot;)
            }
        }
    }
    completion(records.count)
}

Then at the call site you can write:
getNumberOfRecords(category: &quot;classical&quot;, completion: { count in ... })

or better written with trailing-closure syntax:
getNumberOfRecords(category: &quot;classical&quot;) { count in ... }

You still have the problem of three asynchronous things, and instead of chaining them together, you can also avoid looping over the data 3 times, you can loop over the data once and remember the counts for each item, using a dictionary:
private func getNumberOfRecords(completion: ([String: Int] -&gt; Void)) {
    var categoryCounts: [String: Int] = [:]

    {
    ... loop over the data here and instead of switch category ...
    categoryCounts[category] = (categoryCounts[category] ?? 0) + 1
    }

    completion(categoryCounts)
}

getNumberOfRecords { categoryCounts in 
    for (category, count) in categoryCounts {
       loadDataFromDB(records: count, category: category) 
    }
}