I am trying to query data from firebase inside a for loop, my problem is since the queries take time to connect, swift is jumping over the queries and coming back later to do them. This creates the problem where my loop counter is ticking up but the queries are being saved for later, when the queries finally do get executed, the counter variable is all out of wack.
Where the code is being skipped is right after the query, where I am trying to append to an array.
func getSelectedData() {
var exerciseIndex = 0
for i in 0...Master.exercises.count - 1 {
if Master.exercises[i].name == self.exerciseName {
exerciseIndex = i
}
}
let numOfSets = Master.exercises[exerciseIndex].totalSets
// For each date record
for count in 0...self.returnedExercises.count-1 {
// Creates a new dataSet
dataSet.append(dataSetStruct())
dataSet[count].date = returnedExercises[count]
for number in 0...(numOfSets - 1) {
// Retrives the reps
let repsDbCallHistory = db.collection("users").document("\(userId)").collection("ExerciseData").document("AllExercises").collection(exerciseName).document(returnedExercises[count]).collection("Set\(number + 1)").document("reps")
repsDbCallHistory.getDocument { (document, error) in
if let document = document, document.exists {
// For every document (Set) in the database, copy the values and add them to the array
let data:[String:Any] = document.data()!
self.dataSet[count].repsArray.append(data["Reps\(number + 1)"] as! Int)
}
else {
// error
}
}
//Retrives the weights
let weightsDbCallHistory = db.collection("users").document("\(userId)").collection("ExerciseData").document("AllExercises").collection(exerciseName).document(returnedExercises[count]).collection("Set\(number + 1)").document("weights")
weightsDbCallHistory.getDocument { (document, error) in
if let document = document, document.exists {
// For every document (Set) in the database, copy the values and add them to the array
let data:[String:Any] = document.data()!
self.dataSet[count].weightsArray.append(data["Weight\(number + 1)"] as! Float)
self.updateGraph()
}
else {
// error
}
}
}
}
}
I even tried breaking out the query into another function but this doesn't seem to fix the issue.
Any help is appreciated, thanks.
EDIT:
func getSelectedData() {
if returnedExercises.count > 0 {
// Create a dispatch group
let group = DispatchGroup()
print("Getting Data")
// For each date record
for count in 0...self.returnedExercises.count-1 {
// Creates a new dataSet
self.dataSet.append(dataSetStruct())
self.dataSet[count].date = self.returnedExercises[count]
for number in 0...(self.numOfSets - 1) {
print("At record \(count), set \(number)")
// Enter the group
group.enter()
// Start the dispatch
DispatchQueue.global().async {
// Retrives the reps
let repsDbCallHistory = self.db.collection("users").document("\(self.userId)").collection("ExerciseData").document("AllExercises").collection(self.exerciseName).document(self.returnedExercises[count]).collection("Set\(number + 1)").document("reps")
repsDbCallHistory.getDocument { (document, error) in
if let document = document, document.exists {
// For every document (Set) in the database, copy the values and add them to the array
let data:[String:Any] = document.data()!
self.dataSet[count].repsArray.append(data["Reps\(number + 1)"] as! Int)
print("Getting data: \(number)")
group.leave()
}
else {
// error
}
}
}
group.wait()
print("Finished getting data")
}
}
I tried to simplify the function for now and only have one database call in the function to try the dispatch groups. I am not sure why firebase is doing this but the code never executes the group.leave, the program just sits idle. If I am doing something wrong please let me know, thanks.
This is what the print statements are showing:
Getting Data
At record 0, set 0
At record 0, set 1
At record 0, set 2
At record 1, set 0
At record 1, set 1
At record 1, set 2
print("Getting data: (number)") is never being executed for some reason.
I am thinking that maybe firebase calls are ran on a separate thread or something, which would made them pause execution as well, but that's just my theory
EDIT2::
func getOneRepMax(completion: @escaping (_ message: String) -> Void) {
if returnedOneRepMax.count > 0 {
print("Getting Data")
// For each date record
for count in 0...self.returnedOneRepMax.count-1 {
// Creates a new dataSet
oneRPDataSet.append(oneRepMaxStruct())
oneRPDataSet[count].date = returnedOneRepMax[count]
// Retrives the reps
let oneRepMax = db.collection("users").document("\(userId)").collection("UserInputData").document("OneRepMax").collection(exerciseName).document(returnedOneRepMax[count])
oneRepMax.getDocument { (document, error) in
if let document = document, document.exists {
// For every document (Set) in the database, copy the values and add them to the array
let data:[String:Any] = document.data()!
self.oneRPDataSet[count].weight = Float(data["Weight"] as! String)!
print("Getting data: \(count)")
completion("DONE")
self.updateGraph()
}
else {
// error
}
}
}
}
}
I tried using completion handlers for a different function and it is also not working properly.
self.getOneRepMax(completion: { message in
print(message)
})
print("Finished getting data")
The order that the print statements should go:
Getting Data
Getting data: 0
Done
Getting data: 1
Done
Finished getting data
The order that the print statements are coming out right now:
Getting Data
Finished getting data
Getting data: 1
Done
Getting data: 0
Done
I am not even sure how it is possible that the count is backwards since my for loop counts up, what mistake am I making?