使用Geofire/Firebase组合用户列表 [英] Assemble a list of users with Geofire/Firebase

查看:69
本文介绍了使用Geofire/Firebase组合用户列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为User的类,该类具有使用GeoFire获取附近所有食品卡车的功能.我使用了observeReadyWithBlock来获取GeoFire返回的卡车ID,并使用Firebase来获取其余的信息.但是,当我在添加卡车对象的名称和描述之后从我的卡车对象数组访问其中一辆卡车时,似乎xCode告诉我该数组为空.

I have a class called User, which has a function that gets all nearby food trucks using GeoFire. I've used an observeReadyWithBlock to take the truck IDs returned by GeoFire, and get the rest of their information using Firebase. However, when I go to access one of the trucks from my array of Truck objects after adding their name and description, it looks like xCode is telling me the array is empty.

我计划在其他控制器类别中使用这一系列附近的卡车,以填充表格,向用户显示所有附近的卡车和一些基本信息.

I am planning on using this array of nearby trucks in other controller classes, to populate tables showing all of the nearby trucks and some basic information to the user.

如何正确填充卡车阵列,以及基于以下代码的错误提示.非常感谢!

How can I properly populate my array of Trucks, and what could I be getting wrong based on the code below. Thanks very much!

func getNearbyTrucks(){
    //Query GeoFire for nearby users
    //Set up query parameters
    let center = CLLocation(latitude: 37.331469, longitude: -122.029825)
    let circleQuery = geoFire.queryAtLocation(center, withRadius: 100)

    circleQuery.observeEventType(GFEventTypeKeyEntered, withBlock: { (key: String!, location: CLLocation!) in

        let newTruck = Truck()
        newTruck.id = key
        newTruck.currentLocation = location
        self.nearbyTrucks.append(newTruck)

    }) //End truckQuery

    //Execute code once GeoFire is done with its' query!
    circleQuery.observeReadyWithBlock({

        for truck in self.nearbyTrucks{

            ref.childByAppendingPath("users/\(truck.id)").observeEventType(.Value, withBlock: { snapshot in
                print(snapshot.value["name"] as! String)

                truck.name = snapshot.value["name"] as! String
                truck.description = snapshot.value["selfDescription"] as! String
                let base64String = snapshot.value["profileImage"] as! String
                let decodedData = NSData(base64EncodedString: base64String as String, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
                truck.photo = UIImage(data: decodedData!)!
            })
        }

    }) //End observeReadyWithBlock

    print(nearbyTrucks[0].id)
    //This line gives the error that the array index is out of range
}

推荐答案

Geofire和您的Firebase数据库其余部分中的数据并非简单地获取",从数据库中.它被异步加载,然后连续同步.这将更改您的代码流.通过添加一些日志记录,最容易看到这一点:

The data from Geofire and the rest of your Firebase Database is not simply "gotten" from the database. It is asynchronously loaded and then continuously synchronized. This changes the flow of your code. This is easiest to see by adding some logging:

func getNearbyTrucks(){
    //Query GeoFire for nearby users
    //Set up query parameters
    let center = CLLocation(latitude: 37.331469, longitude: -122.029825)
    let circleQuery = geoFire.queryAtLocation(center, withRadius: 100)

    print("Before Geoquery")

    circleQuery.observeEventType(GFEventTypeKeyEntered, withBlock: { (key: String!, location: CLLocation!) in
        print("In KeyEntered block ")

        let newTruck = Truck()
        newTruck.id = key
        newTruck.currentLocation = location
        self.nearbyTrucks.append(newTruck)

    }) //End truckQuery

    print("After Geoquery")
}

日志记录的输出将与您期望的顺序不同:

The output of the logging will be in a different order from what you may expect:

地理查询之前

地理查询之后

在KeyEntered块中

In KeyEntered block

在KeyEntered块中

In KeyEntered block

...

从服务器中检索地理密钥和用户时,代码将继续并getNearbyTrucks()退出,然后返回任何密钥或用户.

While the Geo-keys and users are being retrieved from the server, the code continues and getNearbyTrucks() exits before any keys or users are returned.

一种常见的处理方法是从先装载卡车,然后打印冷杉卡车"中更改您对代码的看法.到无论何时装载卡车,都要打印第一辆卡车".

One common way to deal with this is to change the way you think of your code from "first load the trucks, then print the firs truck" to "whenever the trucks are loaded, print the first one".

在代码中,它转换为:

func getNearbyTrucks(){
    //Query GeoFire for nearby users
    //Set up query parameters
    let center = CLLocation(latitude: 37.331469, longitude: -122.029825)
    let circleQuery = geoFire.queryAtLocation(center, withRadius: 100)

    circleQuery.observeEventType(GFEventTypeKeyEntered, withBlock: { (key: String!, location: CLLocation!) in

        let newTruck = Truck()
        newTruck.id = key
        newTruck.currentLocation = location
        self.nearbyTrucks.append(newTruck)

        print(nearbyTrucks[0].id)
    }) //End truckQuery

    //Execute code once GeoFire is done with its' query!
    circleQuery.observeReadyWithBlock({

        for truck in self.nearbyTrucks{

            ref.childByAppendingPath("users/\(truck.id)").observeEventType(.Value, withBlock: { snapshot in
                print(snapshot.value["name"] as! String)

                truck.name = snapshot.value["name"] as! String
                truck.description = snapshot.value["selfDescription"] as! String
                let base64String = snapshot.value["profileImage"] as! String
                let decodedData = NSData(base64EncodedString: base64String as String, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
                truck.photo = UIImage(data: decodedData!)!
            })
        }

    }) //End observeReadyWithBlock
}

我已将第一辆卡车的打印移到了按键输入事件的块中.根据要尝试运行的实际代码,将其移到其他位置.

I've moved the printing of the first truck into the block for the key entered event. Depending on the actual code you're trying to run, you'll move it into different places.

一种更可重用的方法是Firebase数据库和Geofire自己使用的方法:您将一个块传递到observeEventType withBlock:中,并且该块包含在有密钥时要运行的代码.如果对您的方法应用相同的模式,它将变为:

A more reusable approach is the one the Firebase Database and Geofire themselves use: you pass a block into observeEventType withBlock: and that block contains the code to be run when a key is available. If you apply the same pattern to you method, it'd become:

func getNearbyTrucks(withBlock: (key: String) -> ()){
    //Query GeoFire for nearby users
    //Set up query parameters
    let center = CLLocation(latitude: 37.331469, longitude: -122.029825)
    let circleQuery = geoFire.queryAtLocation(center, withRadius: 100)

    circleQuery.observeEventType(GFEventTypeKeyEntered, withBlock: { (key: String!, location: CLLocation!) in

        let newTruck = Truck()
        newTruck.id = key
        newTruck.currentLocation = location
        self.nearbyTrucks.append(newTruck)

        withBlock(nearbyTrucks[0].id)
    }) //End truckQuery

    //Execute code once GeoFire is done with its' query!
    circleQuery.observeReadyWithBlock({

        for truck in self.nearbyTrucks{

            ref.childByAppendingPath("users/\(truck.id)").observeEventType(.Value, withBlock: { snapshot in
                print(snapshot.value["name"] as! String)

                truck.name = snapshot.value["name"] as! String
                truck.description = snapshot.value["selfDescription"] as! String
                let base64String = snapshot.value["profileImage"] as! String
                let decodedData = NSData(base64EncodedString: base64String as String, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
                truck.photo = UIImage(data: decodedData!)!
            })
        }

    }) //End observeReadyWithBlock
}

再次,您需要根据需要将withBlock()回调移动到更合适的位置.

Here again, you'll want to move the withBlock() callback to a more suitable place depending on your needs.

这篇关于使用Geofire/Firebase组合用户列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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