I have the following swift code to allow for mapping of a users contacts to the webserver, and then show in the tableview:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
dispatch_group_enter(self.dispatch_group)
dispatch_group_async(self.dispatch_group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
print("start 1")
self.contacts = self.findContacts()
dispatch_group_leave(self.dispatch_group)
print("End 1")
}
dispatch_group_enter(self.dispatch_group)
dispatch_group_async(self.dispatch_group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
print("start 2")
// Method to match contacts with Firebase db:
self.mapContactsToPresentFriends(self.contacts, firebaseMainURL: self.firebaseMainURL, usersSyncID: "fdb17f3a-7b7d-4aa5-9a0b-b9fb33c349de")
dispatch_group_leave(self.dispatch_group)
print("End 2")
}
dispatch_group_notify(self.dispatch_group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), {
print("start 3")
// Final load of who is left of conacts (not user or friend)
for contact in self.contacts {
let phoneNumber = contact.phoneNumbers[0].value as! CNPhoneNumber
self.friends.append(Friend(userName: "", phoneNumber: phoneNumber.stringValue, status: 0, name: contact.givenName, userID: ""))
}
for friend in self.friends {
print(friend.status)
}
self.tableView!.reloadData()
})
}
However, noting the print("Start 1"), print("Start 2") and print("Start 3") statements, the log displays the execution as:
start 2
start 1
End 2
End 1
start 3
Which yields an inaccurate result. I need these asynchronous tasks to occur in order (as indicated by the print statements), or else the result will not make sense.
How can this be rearranged to ensure that it works?
You should probably create a serial queue (use the dispatch_queue_create function with the DISPATCH_QUEUE_SERIAL attribute.)
Then submit your tasks to the serial queue. They will still run concurrently with the main thread, but each task in a serial queue completes before the next one starts.
You could also set up barriers at each point where you wanted the previous task to complete before beginning the next, but it sounds like you want ALL of your tasks to run sequentially so a serial queue is a better fit and easier to set up.
If you really want these things to happen in order, there's no need for separate blocks.
Another couple things to note:
dispatch_group_async
replaces the need for_enter()
and_leave()
. You don't need both. (If you had really wanted to use groups, you'd also needdispatch_group_notify
to complete the work.)_async()
is fast).self.tableView.reloadData()
(and UI updates) must happen on the main thread, and consequentially, your data source (e.g.self.friends
) must also be updated on the main thread. I've changed this in the snippet above.