【问题标题】:How to force firebase functions to execute before continuing swift如何在继续快速之前强制执行firebase功能
【发布时间】:2021-06-10 20:42:21
【问题描述】:

我正在尝试在 for 循环中从 firebase 查询数据,我的问题是由于查询需要时间来连接,swift 正在跳过查询并稍后返回执行它们。这会产生问题,我的循环计数器正在增加,但查询被保存以备后用,当查询最终执行时,计数器变量完全不正常。

代码被跳过的地方是在查询之后,我试图追加到一个数组。

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
                }
            }
        }
    }
}

我什至尝试将查询分解为另一个函数,但这似乎无法解决问题。

感谢您的帮助。

编辑:

    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")
    }
}

我现在尝试简化函数,并且函数中只有一个数据库调用来尝试调度组。我不确定为什么 firebase 会这样做,但代码从不执行 group.leave,程序只是闲置。如果我做错了什么,请告诉我,谢谢。

这是打印语句显示的内容:

获取数据
在记录 0 处,设置 0
在记录 0 处,设置 1
在记录 0 处,设置 2
在记录 1 处,设置 0
在记录 1 处,设置 1
在记录 1 处,设置 2

print("Getting data: (number)") 由于某种原因永远不会被执行。

我在想也许 firebase 调用是在单独的线程或其他东西上运行的,这也会使它们暂停执行,但这只是我的理论

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
                }
            }
        }
    }
}

我尝试将完成处理程序用于不同的功能,但它也无法正常工作。

                self.getOneRepMax(completion: { message in
                   print(message)
            })
            
            print("Finished getting data")

打印语句的顺序:
获取数据
获取数据:0
完成
获取数据:1
完成
数据获取完毕

打印语句现在出来的顺序:
获取数据
完成获取数据
获取数据:1
完成
获取数据:0
完成

我什至不确定自从我的 for 循环计数后,计数怎么可能倒退,我犯了什么错误?

【问题讨论】:

  • 请以文本形式发布您的代码,而不是屏幕截图(在手机上难以阅读且存在可访问性问题)
  • 这能回答你的问题吗? Returning data from async call in Swift function
  • 我按照建议更改了图像,但是链接似乎没有帮助,我尝试实现完成处理程序但同样的问题仍然发生@jnpdx
  • 我建议您使用完成处理程序显示更新后的代码
  • 嗨@jnpdx,我在尝试使用完成处理程序的地方添加了代码

标签: ios swift xcode firebase


【解决方案1】:

我认为您需要的是调度组。

let dispatchGroup1 = DispatchGroup()
let dispatchGroup2 = DispatchGroup()

dispatchGroup1.enter() 
firebaseRequest1() { (_, _) in  
   doThings()
dispatchGroup1.leave() 
}

dispatchGroup2.enter() 
dispatchGroup1.notify(queue: .main) {
firebaseRequest2() { (_, _ ) in
doThings()
dispatchGroup2.leave() 
}
dispatchGroup2.notify(queue: .main) {
completionHandler()
}

【讨论】:

  • 嗨,George,我用 Dispatch 组编辑了我的帖子,但如果您能看一下,还是有一些错误,谢谢。 @乔治
猜你喜欢
  • 2020-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-27
  • 2019-08-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多