调度阻塞返回太早(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)
            //}
        }
    }
}

无论我尝试了什么,当点击

时,它总是会抛出"致命错误:在展开可选值时意外发现nil"。
println("raceIdentities.count = (raceIdentities.count)")

因为从这行调用的代码:

self.cloudReadRaceIdentities(self.isMonitor)

还没有发生。

我尝试了注释掉的代码(没有成功),也改变了这一行:

dispatch_async(GlobalUserInitiatedQueue) {

dispatch_sync(GlobalUserInitiatedQueue) {

我还将println语句移出了外壳,结果相同。

我的大部分信息来自raywenderlich.com上的Swift大中央调度教程,但显然我遗漏了一些东西。

任何想法吗?

你必须:

    让你的阅读器功能同步。然后你也可以删除所有的dispatch_group的东西(无论如何它没有做什么你现在有它)
  • 添加一个完成处理程序到你的阅读器函数中,在其中留下dispatch_group
我建议使用第一种方法,它看起来像这样(在使阅读器函数同步之后):
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)
        }
    }
}
第二个方法看起来像这样(在给阅读器函数添加一个完成处理程序参数之后):
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)
        }
    }
}

但是我仍然建议让你的读函数同步,因为你已经在你的方法中异步了

最新更新