Reputation: 357
So I am trying to restructure my API calls to make use of dispatchGroups so I don't have to make collectionViews and other elements reload so quick. I know that with dispatch groups you typically have to create one, enter, and then leave a certain number of times. Upon completion of this, you typically notify the main queue to do some operation. However, in the code snippet below it notifies the main queue before I even enter the dispatch group once. Which is throwing things way off. If anyone could look at my code and tell me what's going wrong I would really appreciate that.
static func showFeaturedEvent(for currentLocation: CLLocation,completion: @escaping ([Event]) -> Void) {
//getting firebase root directory
let dispatchGroup1 = DispatchGroup()
var currentEvents:[Event]?
var geoFireRef: DatabaseReference?
var geoFire:GeoFire?
geoFireRef = Database.database().reference().child("featuredeventsbylocation")
geoFire = GeoFire(firebaseRef: geoFireRef!)
let circleQuery = geoFire?.query(at: currentLocation, withRadius: 17.0)
circleQuery?.observe(.keyEntered, with: { (key: String!, location: CLLocation!) in
print("Key '\(key)' entered the search area and is at location '\(location)'")
dispatchGroup1.enter()
print("entered dispatch group")
EventService.show(forEventKey: key, completion: { (event) in
if let newEvent = event {
currentEvents?.append(newEvent)
dispatchGroup1.leave()
print("left dispatch group")
}
})
})
dispatchGroup1.notify(queue: .main, execute: {
if let currentEventsFinal = currentEvents{
completion(currentEventsFinal)
}
})
}
I am running dispatch groups in other places. Im not sure if that would affect anything but I just felt like it was important to note in this question.
Upvotes: 1
Views: 1204
Reputation: 114836
You need to enter
the group before you start the asynchronous task and leave
in the completion of the asynchronous task. You aren't executing the first enter
until the first asynchronous task completes, so when execution hits your notify
the dispatch group is empty and it fires straight away.
It is also important that you call leave
the same number of times that you call enter
or the group will never empty, so be wary of calling leave
inside conditional statements.
static func showFeaturedEvent(for currentLocation: CLLocation,completion: @escaping ([Event]) -> Void) {
//getting firebase root directory
let dispatchGroup1 = DispatchGroup()
var currentEvents:[Event]?
var geoFireRef: DatabaseReference?
var geoFire:GeoFire?
geoFireRef = Database.database().reference().child("featuredeventsbylocation")
geoFire = GeoFire(firebaseRef: geoFireRef!)
let circleQuery = geoFire?.query(at: currentLocation, withRadius: 17.0)
disatchGroup1.enter()
circleQuery?.observe(.keyEntered, with: { (key: String!, location: CLLocation!) in
print("Key '\(key)' entered the search area and is at location '\(location)'")
dispatchGroup1.enter()
EventService.show(forEventKey: key, completion: { (event) in
if let newEvent = event {
currentEvents?.append(newEvent)
print("left dispatch group")
}
dispatchGroup1.leave()
})
dispatchGroup1.leave()
})
dispatchGroup1.notify(queue: .main, execute: {
if let currentEventsFinal = currentEvents{
completion(currentEventsFinal)
}
})
}
Upvotes: 1