如何编写Firebase数据的完成处理程序? [英] How do I write a completion handler for firebase data?

查看:129
本文介绍了如何编写Firebase数据的完成处理程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我之前有过从firebase的观察工作的问题,我意识到我不能从代码块中异步工作的变量值。用户告诉我使用完成处理程序来解决这个问题,他的例子是:
$ 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆