ios - Set order for background operations with completion handler in main thread -
i have following method executes on background thread every time app starts:
func setup() { loadplayers() loadteams() }
each of these methods invokes webservice, done in background thread, , parse json received load data in memory. reason, these process of parsing data done in main thread.
teams composed players, must set info players before loading teams. how can make this? have tried following code loadteams()
still invoked before players loaded.
func setup() { dispatch_sync(dispatch_get_global_queue(dispatch_queue_priority_default, 0), { self.loadplayers() }) dispatch_sync(dispatch_get_global_queue(dispatch_queue_priority_default, 0), { self.loadteams() }) }
from sounds like, loadplayers()
, loadteams()
functions happening asynchronously. therefore doesn't matter if you're using dispatch_sync
, functions return immediately, dispatch_sync
return immediately.
as trick14 said, need implement callback these functions yourself. imagine 'webservice' you're using implement kind of callback system anyway.
for example, you'd want have functions this:
func loadplayers(callback: () -> ()) { // don't know api you're using, must implement form of callback system... doasynchronousnetworktaskwithcompletion({success in callback() }) }
then can dispatch these tasks onto background queue, using callbacks queue next tasks. example:
func setup() { dispatch_async(dispatch_get_global_queue(dispatch_queue_priority_default, 0), { self.loadplayers({ self.loadteams({ dispatch_async(dispatch_get_main_queue(), { // ui update }) }) }) }) }
the problem method you'll start create pyramid of doom, isn't great readability.
to counter this, can use dispatch_group
schedule completion block fire when given number of tasks have finished. tasks asynchronous, you'll have use functions dispatch_group_enter()
, dispatch_group_leave()
manually increment , decrement number of tasks running.
for example:
func setup() { let group = dispatch_group_create() dispatch_group_enter(group) // increment number of tasks in group loadshirts({ dispatch_group_leave(group) // decrement number of tasks in group print("finished shirts") }) dispatch_group_enter(group) loadstadiums({ dispatch_group_leave(group) print("finished stadiums") }) dispatch_group_enter(group) loadplayers({ dispatch_group_leave(group) print("finished players") }) // gets fired when number of tasks in group reaches zero. dispatch_group_notify(group, dispatch_get_global_queue(dispatch_queue_priority_default, 0), { self.loadteams({ dispatch_async(dispatch_get_main_queue(), { // ui update print("finished") }) }) }) }
it's worth noting using dispatch_sync
onto background queue main queue doesn't guarantee tasks run on background thread.
because you're blocking main thread when this, gcd optimise running code on main thread anyway (as transferring thread expensive). see here more info.
therefore want using dispatch_async
wherever can , synchronising within background operation itself, although doesn't matter in case tasks asynchronous anyway.
Comments
Post a Comment