调度块太早返回(Swift)

时间:2015-07-08 18:51:48

标签: ios multithreading swift grand-central-dispatch

我尝试确保在继续主线程之前完成了我的云访问。我在一个警报操作中调用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 Grand Central Dispatch Tutorial,但显然我错过了一些东西。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

您必须:

  • 让您的阅读器功能同步。然后你也可以删除所有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)
        }
    }
}

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