2016-07-26 5 views
1

사용자 인 GeoFire를 사용하여 근처에있는 모든 음식 트럭을 가져 오는 기능을 가진 사용자 클래스가 있습니다. observeReadyWithBlock을 사용하여 GeoFire가 반환 한 트럭 ID를 가져와 Firebase를 사용하여 나머지 정보를 얻습니다. 그러나 트럭 개체의 배열에서 이름과 설명을 추가 한 후 트럭 중 하나에 액세스하려고하면 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 데이터베이스의 데이터는 단순히 데이터베이스에서 "가져온"것이 아닙니다. 비동기 적으로로드 된 다음 지속적으로 동기화됩니다. 이렇게하면 코드의 흐름이 바뀝니다. Geoquery

Geoquery

전에

후 :

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

로깅의 출력은 예상 할 수 것과는 다른 순서에있을 것입니다 : 이것은 일부 로깅을 추가하여 볼 수있는 가장 쉬운 방법입니다

In 키 입력 블록

In 키 입력 블록

지오 - 키와 사용자가 서버에서 검색되는 동안 16,

...

코드는 계속하고 키 또는 사용자 전에 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

대단히 감사합니다! 정말로 도움이되는, 고맙습니다! –