调度块 return 太早 (Swift)
dispatch blocks return too early (Swift)
我正在尝试确保在继续主线程之前完成我的云访问。我从警报操作中调用 downloadRecordsWithCompletion,所以我在一个封闭空间中。
self.downloadRecordsWithCompletion() {
error in
println("out of alert")
println("raceIdentities.count = \(raceIdentities.count)")
println("raceTeams.count = \(raceTeams.count)")
println("raceTasks.count = \(raceTasks.count)")
self.misc()
}
这里是调用的代码:
func downloadRecordsWithCompletion(completion: (error: NSError?) -> Void) {
dispatch_async(GlobalUserInitiatedQueue) {
var storedError: NSError!
var downloadGroup = dispatch_group_create()
dispatch_group_enter(downloadGroup)
self.cloudReadRaceIdentities(self.isMonitor)
dispatch_group_leave(downloadGroup)
dispatch_group_enter(downloadGroup)
self.cloudReadParameters()
dispatch_group_leave(downloadGroup)
dispatch_group_enter(downloadGroup)
self.cloudReadCheckpoints()
dispatch_group_leave(downloadGroup)
dispatch_group_enter(downloadGroup)
self.cloudReadTeams()
dispatch_group_leave(downloadGroup)
dispatch_group_enter(downloadGroup)
self.cloudReadTasks()
dispatch_group_leave(downloadGroup)
/*
dispatch_group_enter(downloadGroup)
self.cloudReadRaceIdentities(self.isMonitor)
self.cloudReadParameters()
self.cloudReadCheckpoints()
self.cloudReadTeams()
self.cloudReadTasks()
dispatch_group_leave(downloadGroup)
*/
dispatch_group_wait(downloadGroup, DISPATCH_TIME_FOREVER)
dispatch_async(GlobalMainQueue) {
//if let completion = completion {
completion(error: storedError)
//}
}
}
}
不管我怎么试,它总是在命中时抛出"fatal error: unexpectedly found nil while unwrapping an Optional value"
println("raceIdentities.count = \(raceIdentities.count)")
因为从这一行调用的代码:
self.cloudReadRaceIdentities(self.isMonitor)
还没有发生。
我尝试了注释掉的代码(没有成功)并且还更改了这一行:
dispatch_async(GlobalUserInitiatedQueue) {
至此
dispatch_sync(GlobalUserInitiatedQueue) {
我也将 println 语句移到了外壳之外,结果相同。
我的大部分信息来自 raywenderlich.com 他为 Swift 编写的 Grand Central Dispatch 教程,但显然我遗漏了一些东西。
有什么想法吗?
您必须:
- 使您的 reader 函数同步。然后你也可以删除所有
dispatch_group
东西(反正你现在拥有它什么都不做)
- 向您的 reader 函数添加一个完成处理程序,您在其中保留
dispatch_group
我建议使用第一种方法,它看起来像这样(在使 reader 函数同步之后):
func downloadRecordsWithCompletion(completion: (error: NSError?) -> Void) {
dispatch_async(GlobalUserInitiatedQueue) {
self.cloudReadRaceIdentities(self.isMonitor)
self.cloudReadParameters()
self.cloudReadCheckpoints()
self.cloudReadTeams()
self.cloudReadTasks()
dispatch_async(GlobalMainQueue) {
completion(error: nil)
}
}
}
第二种方法看起来像这样(在向 reader 函数添加完成处理程序参数之后):
func downloadRecordsWithCompletion(completion: (error: NSError?) -> Void) {
dispatch_async(GlobalUserInitiatedQueue) {
let downloadGroup = dispatch_group_create()
dispatch_group_enter(downloadGroup)
self.cloudReadRaceIdentities(self.isMonitor) {
dispatch_group_leave(downloadGroup)
}
dispatch_group_enter(downloadGroup)
self.cloudReadParameters() {
dispatch_group_leave(downloadGroup)
}
dispatch_group_enter(downloadGroup)
self.cloudReadCheckpoints() {
dispatch_group_leave(downloadGroup)
}
dispatch_group_enter(downloadGroup)
self.cloudReadTeams() {
dispatch_group_leave(downloadGroup)
}
dispatch_group_enter(downloadGroup)
self.cloudReadTasks() {
dispatch_group_leave(downloadGroup)
}
dispatch_group_wait(downloadGroup, DISPATCH_TIME_FOREVER)
dispatch_async(GlobalMainQueue) {
completion(error: nil)
}
}
}
哦,这也可能行不通(忘了上面这个),因为只有一组,但可以保留多个点。所以你可能想使用一个 dispatch_semaphore
等待直到它被发出 n 次这样的信号:
func downloadRecordsWithCompletion(completion: (error: NSError?) -> Void) {
dispatch_async(GlobalUserInitiatedQueue) {
let semaphore = dispatch_semaphore_create(5)
self.cloudReadRaceIdentities(self.isMonitor) {
dispatch_semaphore_signal(semaphore)
}
self.cloudReadParameters() {
dispatch_semaphore_signal(semaphore)
}
self.cloudReadCheckpoints() {
dispatch_semaphore_signal(semaphore)
}
self.cloudReadTeams() {
dispatch_semaphore_signal(semaphore)
}
self.cloudReadTasks() {
dispatch_semaphore_signal(semaphore)
}
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
dispatch_async(GlobalMainQueue) {
completion(error: nil)
}
}
}
但我仍然建议让您同步读取函数,因为您的方法中已经是异步的
我正在尝试确保在继续主线程之前完成我的云访问。我从警报操作中调用 downloadRecordsWithCompletion,所以我在一个封闭空间中。
self.downloadRecordsWithCompletion() {
error in
println("out of alert")
println("raceIdentities.count = \(raceIdentities.count)")
println("raceTeams.count = \(raceTeams.count)")
println("raceTasks.count = \(raceTasks.count)")
self.misc()
}
这里是调用的代码:
func downloadRecordsWithCompletion(completion: (error: NSError?) -> Void) {
dispatch_async(GlobalUserInitiatedQueue) {
var storedError: NSError!
var downloadGroup = dispatch_group_create()
dispatch_group_enter(downloadGroup)
self.cloudReadRaceIdentities(self.isMonitor)
dispatch_group_leave(downloadGroup)
dispatch_group_enter(downloadGroup)
self.cloudReadParameters()
dispatch_group_leave(downloadGroup)
dispatch_group_enter(downloadGroup)
self.cloudReadCheckpoints()
dispatch_group_leave(downloadGroup)
dispatch_group_enter(downloadGroup)
self.cloudReadTeams()
dispatch_group_leave(downloadGroup)
dispatch_group_enter(downloadGroup)
self.cloudReadTasks()
dispatch_group_leave(downloadGroup)
/*
dispatch_group_enter(downloadGroup)
self.cloudReadRaceIdentities(self.isMonitor)
self.cloudReadParameters()
self.cloudReadCheckpoints()
self.cloudReadTeams()
self.cloudReadTasks()
dispatch_group_leave(downloadGroup)
*/
dispatch_group_wait(downloadGroup, DISPATCH_TIME_FOREVER)
dispatch_async(GlobalMainQueue) {
//if let completion = completion {
completion(error: storedError)
//}
}
}
}
不管我怎么试,它总是在命中时抛出"fatal error: unexpectedly found nil while unwrapping an Optional value"
println("raceIdentities.count = \(raceIdentities.count)")
因为从这一行调用的代码:
self.cloudReadRaceIdentities(self.isMonitor)
还没有发生。
我尝试了注释掉的代码(没有成功)并且还更改了这一行:
dispatch_async(GlobalUserInitiatedQueue) {
至此
dispatch_sync(GlobalUserInitiatedQueue) {
我也将 println 语句移到了外壳之外,结果相同。
我的大部分信息来自 raywenderlich.com 他为 Swift 编写的 Grand Central Dispatch 教程,但显然我遗漏了一些东西。
有什么想法吗?
您必须:
- 使您的 reader 函数同步。然后你也可以删除所有
dispatch_group
东西(反正你现在拥有它什么都不做) - 向您的 reader 函数添加一个完成处理程序,您在其中保留
dispatch_group
我建议使用第一种方法,它看起来像这样(在使 reader 函数同步之后):
func downloadRecordsWithCompletion(completion: (error: NSError?) -> Void) {
dispatch_async(GlobalUserInitiatedQueue) {
self.cloudReadRaceIdentities(self.isMonitor)
self.cloudReadParameters()
self.cloudReadCheckpoints()
self.cloudReadTeams()
self.cloudReadTasks()
dispatch_async(GlobalMainQueue) {
completion(error: nil)
}
}
}
第二种方法看起来像这样(在向 reader 函数添加完成处理程序参数之后):
func downloadRecordsWithCompletion(completion: (error: NSError?) -> Void) {
dispatch_async(GlobalUserInitiatedQueue) {
let downloadGroup = dispatch_group_create()
dispatch_group_enter(downloadGroup)
self.cloudReadRaceIdentities(self.isMonitor) {
dispatch_group_leave(downloadGroup)
}
dispatch_group_enter(downloadGroup)
self.cloudReadParameters() {
dispatch_group_leave(downloadGroup)
}
dispatch_group_enter(downloadGroup)
self.cloudReadCheckpoints() {
dispatch_group_leave(downloadGroup)
}
dispatch_group_enter(downloadGroup)
self.cloudReadTeams() {
dispatch_group_leave(downloadGroup)
}
dispatch_group_enter(downloadGroup)
self.cloudReadTasks() {
dispatch_group_leave(downloadGroup)
}
dispatch_group_wait(downloadGroup, DISPATCH_TIME_FOREVER)
dispatch_async(GlobalMainQueue) {
completion(error: nil)
}
}
}
哦,这也可能行不通(忘了上面这个),因为只有一组,但可以保留多个点。所以你可能想使用一个 dispatch_semaphore
等待直到它被发出 n 次这样的信号:
func downloadRecordsWithCompletion(completion: (error: NSError?) -> Void) {
dispatch_async(GlobalUserInitiatedQueue) {
let semaphore = dispatch_semaphore_create(5)
self.cloudReadRaceIdentities(self.isMonitor) {
dispatch_semaphore_signal(semaphore)
}
self.cloudReadParameters() {
dispatch_semaphore_signal(semaphore)
}
self.cloudReadCheckpoints() {
dispatch_semaphore_signal(semaphore)
}
self.cloudReadTeams() {
dispatch_semaphore_signal(semaphore)
}
self.cloudReadTasks() {
dispatch_semaphore_signal(semaphore)
}
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
dispatch_async(GlobalMainQueue) {
completion(error: nil)
}
}
}
但我仍然建议让您同步读取函数,因为您的方法中已经是异步的