每次应用启动时,我都会在后台线程上执行以下方法:
func setup() {
loadPlayers()
loadTeams()
}
这些方法中的每一个都调用webService,它也在后台线程中完成,并解析JSON收到的数据以在内存中加载数据。出于某种原因,这些解析数据的过程是在主线程中完成的。
球队由球员组成,因此我必须在加载球队之前设置球员的所有信息。我该怎么做?我尝试了以下代码,但在加载所有播放器之前仍然会调用loadTeams()
。
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()
})
}
答案 0 :(得分:2)
听起来,您的loadPlayers()
和loadTeams()
函数是异步发生的。因此,如果您使用dispatch_sync
并不重要,因为函数会立即返回,dispatch_sync
也会立即返回。
As trick14 said,您需要自己实现对这些函数的回调。我会想象' webService'你正在使用它会实现某种回调系统。
例如,您希望让您的功能执行以下操作:
func loadPlayers(callback: () -> ()) {
// I don't know what API you're using, but it must implement some form of callback system...
doAsynchronousNetworkTaskWithCompletion({success in
callback()
})
}
然后,您可以简单地将这些任务分派到后台队列,使用回调对下一个任务进行排队。例如:
func setup() {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
self.loadPlayers({
self.loadTeams({
dispatch_async(dispatch_get_main_queue(), {
// do UI update
})
})
})
})
}
这种方法唯一的问题是你会开始创建一个厄运金字塔,这对于提高可读性并不是很好。
要解决此问题,您可以使用dispatch_group
来安排在完成给定数量的任务时触发的完成块。由于您的任务是异步的,因此您必须使用函数dispatch_group_enter()
和dispatch_group_leave()
来手动增加和减少正在运行的任务数。
例如:
func setup() {
let group = dispatch_group_create()
dispatch_group_enter(group) // Increment the number of tasks in the group
loadShirts({
dispatch_group_leave(group) // Decrement the number of tasks in the 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 the number of tasks in the group reaches zero.
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
self.loadTeams({
dispatch_async(dispatch_get_main_queue(), {
// do UI update
print("finished")
})
})
})
}
还值得注意的是,在主队列中使用dispatch_sync
到后台队列并不能保证任务将在后台线程上运行。
因为你在执行此操作时会阻塞主线程,所以GCD通常只需在主线程上运行该代码进行优化(因为转移到另一个线程很昂贵)。 See here for more info.
因此,您希望尽可能使用dispatch_async
并在后台操作本身中进行同步,尽管这在您的情况下并不重要,因为您的任务无论如何都是异步的。