2016-07-26 64 views
1

我有一個名爲User的類,它具有使用GeoFire獲取所有附近食品卡車的功能。我使用了一個observeReadyWithBlock來獲取由GeoFire返回的卡車ID,並使用Firebase獲取其餘的信息。但是,當我在添加名稱和描述後從我的Truck對象數組中訪問其中一輛卡車時,它看起來像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

輸入鍵塊

輸入鍵塊

...

雖然正在從服務器檢索到的地理密鑰和用戶,代碼繼續和任何按鍵或用戶之前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()回調移動到更合適的地方。

+0

非常坦率的謝謝!真的很有幫助,謝謝! –