2016-07-26 6 views
1

私はGeoFireを使用して近くの食品トラックをすべて取得する機能を持つUserというクラスを持っています。私はobserveReadyWithBlockを使ってGeoFireから返されたトラックIDを取得し、Firebaseを使って残りの情報を取得しました。しかし、Truckオブジェクトの名前と説明を追加した後、私のトラックからトラックの1つにアクセスすると、xCodeが配列が空であるとわかります。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) 

    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 
} 

答えて

3

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

ログの出力は、あなたが期待するものとは異なる順序で次のようになります:これは、いくつかのログを追加することによって、一番見やすい

Geoquery

前Geoquery

Inキー入りブロック

Inキー入りブロック

...

ジオキーと、ユーザーはサーバーから取得されている間、コードが続行され、任意のキーまたはユーザーの前にgetNearbyTrucks()出口が返されます。

これに対処する一般的な方法の1つは、コードを「最初にトラックをロードしてから、最初のトラックを印刷する」から「トラックがロードされたときに最初のものをプリントする」というコードを変更することです。コードで

これはに変換:私はにキー入力されたイベントのブロックを最初のトラックの印刷を動かしてきた

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()コールバックを移動したいと思います。

+0

ありがとうございました。本当に本当に有益な、よかった! –

関連する問題