如何编写Firebase数据的完成处理程序? [英] How do I write a completion handler for firebase data?
问题描述
$ b
func mapRegion(completion:(MKCoordinateRegion)在
$ b $中有$ {
databaseHandle = databaseRef.child(RunList)。child(runName).observe(.value, b让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,
lo ngitudeDelta:(self.maxLng! - self.minLng!)* 1.1))
completion(region)
))
}
并使用代码:
mapRegion(){region in
mapView.region = region
//对区域进行其他处理
code $ $ $ $ $ $ $所以我试图重新创建这个另一个方法,我需要返回一个对象类型RunDetail数组:
func loadRuns(completion:(RunDetail)) - >()){
//我们需要名字,距离,时间和用户
databaseHandle = databaseRef.child(RunList) .observe(.value):{(snapshot)in
$ b $ self.count = Int(snapshot.childrenCount)
print(self.count!)
//更多的东西发生在这里添加数据到一个名为RunDetail的对象从firebase
//将RunDetail对象添加到名为run的数组
)完成(运行)
}
我不确定如果我正确地设置上面^。
我仍然无法得到我的头在得到完成处理程序工作(我真的不知道如何设置它) 。有人可以帮助我,让我知道如果我正确地设置了这一点?谢谢。
解决方案您需要将完成(地区)
在Firebase完成块内部,在完成之后添加 @escaping
:
。
另外,您不应该强制展开optionals。很容易检查它们是不是 nil
,这样可以防止应用程序崩溃。
func mapRegion(completion:@escaping(MKCoordinateRegion?) - > Void){
let ref = Database.database()。reference()
ref.child(RunList)。child(runName).observe(.value,其中:{(snapshot)in
guard
让runData = snapshot。值为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)
完成(nil)
返回
}
var region = MKCoordinateRegion()
region.center = CLLocationCoordinate2D(纬度:(minLat + maxLat)/ 2,经度:(minLng + maxLng)/ 2)
region.span = MKCoordinateSpanMake((maxLat - minLat)* 1.1,(maxLng - minLng)* 1.1)
完成(地区)
))
}
然后更新你的代码到这个。
覆盖func viewDidLoad(){
super.viewDidLoad()
//执行任何其他设置加载视图,通常从一个笔尖。
mapRegion {(region)in
if region = region {
self.mapView.setRegion(region,animated:true)
$ b $ p $对于你的 loadRuns(完成:@escaping(Array< RunDetail>) - >无效)
{
let ref = Database.database()。reference()
ref.child(RunList)。observe(.value,with:{(snapshot)in
$ b var runs = Array< RunDetail>()
//填充运行数组
$ b $完成(运行)//这行必须是在这个闭包中。
})
}
So I had issues previously working with 'observe' from firebase, and I realised I could not bring the variable values from inside the code block that was working asynchronously. A user told me to use completion handlers to resolve this issue, and his example was:
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)
})
}
and to use the code:
mapRegion() { region in
mapView.region = region
// do other things with the region
}
So I've tried to recreate this for another method that I need to return an array of object type 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)
}
I am not sure if I am setting this up correctly above^.
I still cannot get my head around getting the completion handler working (I really don't understand how to set it up). Can someone please help me and let me know if I am setting this up properly? Thanks.
解决方案 You need to move the completion(region)
to inside the Firebase completion block and add @escaping
after completion:
.
Also, you should not force unwrap optionals. It is easy enough to check that they are not nil
and this will prevent the app from crashing.
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)
})
}
Then update your code to this.
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)
}
}
}
For your 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.
})
}
这篇关于如何编写Firebase数据的完成处理程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!