GeoFire наблюдаем, что преждевременно исполняется в Swift - PullRequest
0 голосов
/ 29 марта 2019

В следующей функции я выполняю начальный поисковый запрос Geofire и хочу обработать все найденные ключи, добавить их в массив и отправить весь массив обратно.

Проблема в том, что блок кода observeReady выполняется слишком преждевременно и поэтому отправляет пустой массив (при первой загрузке ничего не отображается, даже если в пределах диапазона обнаружены ключи).

Я понимаю, что вызов observeSingleEvent является asynchronous и может вызывать такое поведение, поэтому мой вопрос состоит в том, как я могу управлять этим и обеспечить обработку ключей до выполнения вызова handler в observeReady блок?

func fetchInitialNearbyVenues(deviceLocation: CLLocation, radius: Double, handler: @escaping ([Venue]) -> ()) {

        self.venuesArray.removeAll() 
        var savedByUsers = [String : String]() 

        let query = self.GEOFIRE_VENUES_LOC.query(at: deviceLocation, withRadius: radius) 

            query.observe(.keyEntered) { (key: String!, venueLocation: CLLocation!) in 

                self.REF_VENUES.child(key).observeSingleEvent(of: .value, with: { (snapshot) in 

                  //process snapshot create and append Venue object to array
                  //...
                  //...

                  self.venuesArray.append(venue) //append Venue to array

                })//end observeSingleEvent

            }//end geofire query observe

        query.observeReady {
            handler(self.venuesArray) //PROBLEM: This gets executed prematurely thus sending an empty array via handler 
        }

    }//end func

1 Ответ

0 голосов
/ 29 марта 2019

То, что вы видите, - это ожидаемое поведение.observeReady гарантированно сработает после того, как все соответствующие observe(.keyEntered) были вызваны.Вы можете проверить это с помощью нескольких простых инструкций регистрации:

query.observe(.keyEntered) { (key: String!, venueLocation: CLLocation!) in 
   print(".keyEntered")
}
query.observeReady {
   print(".observeReady")
}

Когда вы запустите это, он напечатает:

.keyEntered

.keyEntered

...

.observeReady

Это соответствует тому, как должен работать API.Но в .keyEntered вы загружаете дополнительные данные из Firebase, что происходит асинхронно.И эти вызовы могут действительно завершиться после , когда .observeReady сработал.

Так что вам нужно будет выполнить необходимую синхронизацию самостоятельно.Простой способ определить, загрузили ли вы все дополнительные данные, - это вести учет всех ключей, для которых вам все еще нужно загрузить данные.Таким образом, вы +1 это каждый раз, когда вы добавляете ключ, и -1 каждый раз, когда вы загружаете данные места:

let venuesToLoadCount = 0
query.observe(.keyEntered) { (key: String!, venueLocation: CLLocation!) in 
   venuesToLoadCount = venuesToLoadCount + 1
   self.REF_VENUES.child(key).observeSingleEvent(of: .value, with: { (snapshot) in     
        venuesToLoadCount = venuesToLoadCount - 1
        if venuesToLoadCount == 0 {
            print("All done")
        }
    }
}
query.observeReady {
    if venuesToLoadCount == 0 {
        print("All done")
    }
}
...