如何为firebase数据编写完成处理程序?

所以我之前遇到过来自firebase的’observe’的问题,我意识到我无法从异步工作的代码块中带来变量值。 用户告诉我使用完成处理程序来解决此问题,他的示例是:

func mapRegion(completion: (MKCoordinateRegion)->()) { databaseHandle = databaseRef.child("RunList").child(runName).observe(.value, with: { (snapshot) in let runData = snapshot.value as? [String: AnyObject] self.minLat = runData?["startLat"] as? Double self.minLng = runData?["startLong"] as? Double self.maxLat = runData?["endLat"] as? Double self.maxLng = runData?["endLong"] as? Double print("testing") print(self.minLat!) print(self.maxLng!) let region = MKCoordinateRegion( center: CLLocationCoordinate2D(latitude: (self.minLat! + self.maxLat!)/2, longitude: (self.minLng! + self.maxLng!)/2), span: MKCoordinateSpan(latitudeDelta: (self.maxLat! - self.minLat!)*1.1, longitudeDelta: (self.maxLng! - self.minLng!)*1.1)) completion(region) }) } 

并使用代码:

 mapRegion() { region in mapView.region = region // do other things with the region } 

所以我试图重新创建另一个方法,我需要返回一个对象类型RunDetail数组:

 func loadRuns(completion: ([RunDetail]) -> ()) { // we need name, distance, time and user databaseHandle = databaseRef.child("RunList").observe(.value, with: { (snapshot) in self.count = Int(snapshot.childrenCount) print(self.count!) // more stuff happening here to add data into an object called RunDetail from firebase // add RunDetail objects into array called 'run' }) completion(runs) } 

我不确定我是否正确设置了^。

我仍然无法理解让完成处理程序工作(我真的不明白如何设置它)。 如果我正确设置,有人可以帮助我并让我知道吗? 谢谢。

您需要将completion(region)移动到Firebase完成块内,并在completion:添加@escaping completion: .

此外,您不应强制解包选项。 很容易检查它们是否nil ,这将阻止应用程序崩溃。

 func mapRegion(completion: @escaping (MKCoordinateRegion?) -> Void) { let ref = Database.database().reference() ref.child("RunList").child(runName).observe(.value, with: { (snapshot) in guard let runData = snapshot.value as? Dictionary, let minLat = runData["startLat"], let minLng = runData["startLong"], let maxLat = runData["endLat"], let maxLng = runData["endLong"] else { print("Error! - Incomplete Data") completion(nil) return } var region = MKCoordinateRegion() region.center = CLLocationCoordinate2D(latitude: (minLat + maxLat) / 2, longitude: (minLng + maxLng) / 2) region.span = MKCoordinateSpanMake((maxLat - minLat) * 1.1, (maxLng - minLng) * 1.1) completion(region) }) } 

然后将您的代码更新为此。

 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. mapRegion { (region) in if let region = region { self.mapView.setRegion(region, animated: true) } } } 

对于你的loadRuns

 func loadRuns(completion: @escaping (Array) -> Void) { let ref = Database.database().reference() ref.child("RunList").observe(.value, with: { (snapshot) in var runs = Array() // Populate runs array. completion(runs) // This line needs to be inside this closure. }) }