【问题标题】:Assemble a list of users with Geofire/Firebase使用 Geofire/Firebase 收集用户列表
【发布时间】:2016-11-29 14:40:30
【问题描述】:

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

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

如何正确填充我的卡车数组,根据下面的代码,我可能会出错。非常感谢!

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
}

【问题讨论】:

    标签: swift xcode firebase firebase-realtime-database geofire


    【解决方案1】:

    来自 Geofire 和 Firebase 数据库其余部分的数据不仅仅是从数据库中“获取”的。它是异步加载的,然后连续同步。这会改变您的代码流程。通过添加一些日志记录最容易看到这一点:

    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")
    }
    

    日志输出的顺序可能与您预期的不同:

    地理查询之前

    地理查询后

    在 KeyEntered 块中

    在 KeyEntered 块中

    ...

    当从服务器检索地理密钥和用户时,代码继续,getNearbyTrucks() 在返回任何密钥或用户之前退出。

    解决此问题的一种常见方法是将您对代码的看法从“首先装载卡车,然后打印第一辆卡车”改为“每当装载卡车时,打印第一辆卡车”。

    在代码中,这转换为:

    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
    }
    

    我已将第一辆卡车的打印移到键输入事件的块中。根据您尝试运行的实际代码,您会将其移动到不同的位置。

    一种更可重用的方法是 Firebase 数据库和 Geofire 自己使用的方法:您将一个块传递给 observeEventType withBlock:,该块包含在密钥可用时要运行的代码。如果您将相同的模式应用于您的方法,它会变成:

    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() 回调移动到更合适的位置。

    【讨论】:

    • 非常感谢坦率!真的很有帮助,谢谢!
    猜你喜欢
    • 2018-12-13
    • 1970-01-01
    • 2018-06-12
    • 1970-01-01
    • 2018-09-04
    • 2016-03-24
    • 2020-05-06
    • 1970-01-01
    相关资源
    最近更新 更多