Swift 如何在for循环之外执行代码(需要等待循环从Firebase数据库检索完数据)?

Swift 如何在for循环之外执行代码(需要等待循环从Firebase数据库检索完数据)?,swift,for-loop,firebase-realtime-database,mkdirection,Swift,For Loop,Firebase Realtime Database,Mkdirection,我试图显示一个表视图,它按汽车旅行时间显示机构 查询循环通过数据库中的学校列表来检索它们的坐标 计算距用户当前位置的距离 如果距离小于20英里,则使用MKDirections()计算eta时间 计算eta时间后,将相关信息附加到表视图的数组中,按eta时间对数组进行排序,只保留前10个 这里的问题是,在用户当前位置的20英里范围内通常有许多机构,MKDirections()限制了您在给定时间范围内计算eta时间的请求量。因此,我的表视图常常无法显示eta时间 对我来说,最明显的解决方案是在计算e

我试图显示一个表视图,它按汽车旅行时间显示机构

  • 查询循环通过数据库中的学校列表来检索它们的坐标
  • 计算距用户当前位置的距离
  • 如果距离小于20英里,则使用MKDirections()计算eta时间
  • 计算eta时间后,将相关信息附加到表视图的数组中,按eta时间对数组进行排序,只保留前10个
  • 这里的问题是,在用户当前位置的20英里范围内通常有许多机构,MKDirections()限制了您在给定时间范围内计算eta时间的请求量。因此,我的表视图常常无法显示eta时间

    对我来说,最明显的解决方案是在计算eta时间之前对数组进行排序和修剪(从而避免了计算eta请求过多的问题)

    我尝试的是:

  • 将for循环内的数据附加到“Array1”
  • 排序和修剪阵列1
  • 在for循环之外/之后,我通过Array1循环以计算eta时间,然后将此数据附加到Array2,该数组将为tableview提供数据
  • 我发现这不起作用,因为for循环外部/之后的代码是在for循环完成之前执行的

                let schoolDB = Database.database().reference().child("Schools")
                schoolDB.observe(.value, with: { (snapshot) in
                    self.subjectTimesArray.removeAll()
                    for child in snapshot.children {
                        let schoolSnapshot = child as! DataSnapshot
                        let approvalString = schoolSnapshot.childSnapshot(forPath: "Approved").value as! String
                        if approvalString == "Yes" {
                            let schoolID = schoolSnapshot.key
                            let schoolName = schoolSnapshot.childSnapshot(forPath: "Name").value as! String
                            let schoolLatitude = schoolSnapshot.childSnapshot(forPath: "Latitude").value as! Double
                            let schoolLongitude = schoolSnapshot.childSnapshot(forPath: "Longitude").value as! Double
                            let schoolLocation = CLLocation(latitude: schoolLatitude, longitude: schoolLongitude)
                            let distance = schoolLocation.distance(from: self.userLocation) / 1600
                            
                            if distance < 20 {
                                let subjectDB = Database.database().reference().child("Subject/" + schoolID + "/" + date)
                                subjectDB.observeSingleEvent(of: .value, with: { (subjectSnapshot) in
                                    let startTime = subjectSnapshot.childSnapshot(forPath: "Maths/Start").value as! String
                                        
                                    let userPlacemark = MKMapItem(placemark: MKPlacemark(coordinate: userLocation.coordinate))
                                    let schoolPlacemark = MKMapItem(placemark: MKPlacemark(coordinate: schoolLocation.coordinate))
                                    let directionsRequest = MKDirections.Request()
                                    directionsRequest.source = userPlacemark
                                    directionsRequest.destination = schoolPlacemark
                                    directionsRequest.requestsAlternateRoutes = false
                                    directionsRequest.transportType = .automobile
                                        
                                    let directions = MKDirections(request: directionsRequest)
                                    directions.calculateETA(completionHandler: { (response, error) in
                                        if let seconds = response?.expectedTravelTime {
                                            let minutes = seconds / 60    
                                            self.subjectTimesArray.append(.init(schoolID: schoolID, schoolName: schoolName, distance: distance, eta: Int(minutes), subjectStart: startTime))
                                        }
                                        
                                        self.subjectTimesArray.sort(by: {$0.eta < $1.eta})
                                        if self.subjectTimesArray.count > 10 {
                                                self.subjectTimesArray.removeLast(self.subjectTimesArray.count - 10)
                                        }
                                        self.subjectTimesTableView.reloadData()
                                    })
                                })
                            }
                        }
                    }
                })
    
    让schoolDB=Database.Database().reference().child(“学校”)
    schoolDB.observe(.value,其中:{(快照)位于
    self.subjectTimesArray.removeAll()
    对于snapshot.children中的子对象{
    让schoolSnapshot=child as!DataSnapshot
    让approvalString=schoolSnapshot.childSnapshot(forPath:“Approved”)。值为!字符串
    如果approvalString==“是”{
    让schoolID=schoolSnapshot.key
    让schoolName=schoolsapshot.childSnapshot(forPath:“Name”)。值为!字符串
    让schoolLatitude=schoolSnapshot.childSnapshot(forPath:“Latitude”)。值为!Double
    让SchoolLength=schoolSnapshot.childSnapshot(forPath:“经度”)。值为!Double
    let schoolLocation=CLLocation(纬度:学校纬度,经度:学校经度)
    让距离=学校位置。距离(from:self.userLocation)/1600
    如果距离<20{
    让subjectDB=Database.Database().reference().child(“Subject/”+schoolID+“/”+date)
    subjectDB.ObservesingEvent(of:.值,其中:{(subjectSnapshot))位于
    让startTime=subjectSnapshot.childSnapshot(forPath:“数学/开始”)。值为!字符串
    让userPlacemark=MKMapItem(placemark:MKPlacemark(坐标:userLocation.coordinate))
    让schoolPlacemark=MKMapItem(placemark:MKPlacemark(坐标:schoolLocation.coordinate))
    let directionrequest=MKDirections.Request()
    DirectionRequest.source=userPlacemark
    DirectionRequest.destination=学校地点标记
    DirectionRequest.RequestSalterRoutes=false
    DirectionRequest.transportType=.automobile
    let directions=MKDirections(请求:directionrequest)
    completionHandler:{(响应,错误)在
    如果let seconds=响应?.expectedTravelTime{
    让分钟=秒/60
    self.subjectTimeArray.append(.init(schoolID:schoolID,schoolName:schoolName,distance:distance,eta:Int(分钟),subjectStart:startTime))
    }
    self.subjectTimesArray.sort(按:{$0.eta<$1.eta})
    如果self.subjectTimesArray.count>10{
    self.subjectTimesArray.removeLast(self.subjectTimesArray.count-10)
    }
    self.subjectTimesTableView.reloadData()
    })
    })
    }
    }
    }
    })
    
    您可以创建一个函数,该函数使用一个参数作为学校来计算距离,并在距离小于20英里时调用该函数;或者,如果距离小于20英里,则将数据库中的每个学校附加到一个新数组中,并根据该数组进行计算。如果您选择第二个选项,它将只在20英里以下的学校中循环,我建议您选择第一个选项。

    您可以创建一个函数,使用一个参数作为学校来计算距离,并在距离小于20英里时调用它,或者将数据库中的每个学校添加到一个新数组中(如果距离不足20英里),然后计算该数组。如果你做第二个选择,它将只在20英里以下的学校中循环,我推荐第一个选择