首页 > 解决方案 > GeoFire observeReady 在 Swift 中过早执行

问题描述

在以下函数中,我正在执行初始 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

标签: swiftfirebasegeofire

解决方案


你看到的是预期的行为。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")
    }
}

推荐阅读