Как мне написать обработчик завершения для данных Firebase?
Поэтому у меня были проблемы, ранее работавшие с "наблюдением" из firebase, и я понял, что не могу вывести значения переменных из блока кода, который работал асинхронно. Пользователь сказал мне использовать обработчики завершения для решения этой проблемы, и его пример был:
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)
}
Я не уверен, правильно ли я настраиваю это выше ^.
Я все еще не могу понять, как работает обработчик завершения (я действительно не понимаю, как его настроить). Может кто-нибудь помочь мне и сообщить, правильно ли я это настраиваю? Благодарю.
1 ответ
Вам нужно переместить completion(region)
внутрь блока завершения Firebase и добавить @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<String,Double>,
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<RunDetail>) -> Void) {
let ref = Database.database().reference()
ref.child("RunList").observe(.value, with: { (snapshot) in
var runs = Array<RunDetail>()
// Populate runs array.
completion(runs) // This line needs to be inside this closure.
})
}