如何以正确的方式在Swift中调度函数?

Ale*_* S. 12 grand-central-dispatch swift ios8

我一直在努力,但我只是不明白.我对编程很陌生,所以几乎每一个新步骤都是一个实验.虽然在没有参数/返回的情况下调度普通闭包没有问题,但到目前为止我还没有理解如何处理带有(多个)参数并最终返​​回的函数.

为了获得正确的"解决方案"的逻辑,如果有人能够发布一个实际的例子,那将是很好的,所以我可以看到我是否已经完全正确.我会非常感谢任何帮助...如果其他一些实际例子以更好的方式说明了这个话题,请继续自己做!

假设我们想要将以下函数异步调度到具有低优先级的后台队列(或者我犯了错误,在定义函数时尝试实现调度而不是等到从其他地方调用它?!):

func mutateInt(someInt: Int) -> Int {
    "someHeavyCalculations"
    return result
}
Run Code Online (Sandbox Code Playgroud)

或者是一个带有多个参数的函数,它还会在某个时刻调用第一个函数(后台队列中的所有内容):

func someBadExample(someString: String, anotherInt: Int) -> Int {
    "someHeavyStuff"
    println(testString)
    mutateInt(testInt)
    return result
}
Run Code Online (Sandbox Code Playgroud)

或者应该确保在主队列上运行的UI函数(只是一个虚构的例子):

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {        
    let sectionInfo = self.fetchedResultsController.sections?[section] as NSFetchedResultsSectionInfo       
    return sectionInfo.numberOfObjects
}
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 23

假设你有一些这样的功能:

func calculate(foo: String, bar: Int) -> Int {
    // slow calculations performed here

    return result
}
Run Code Online (Sandbox Code Playgroud)

如果你想异步地这样做,你可以把它包装成这样的东西:

func calculate(foo: String, bar: Int, completionHandler: @escaping (Int) -> Void) {
    DispatchQueue.global().async {
        // slow calculations performed here

        completionHandler(result)
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,或者,如果您想确保始终在主队列上调用完成处理程序,您也可以为此执行此操作:

func calculate(foo: String, bar: Int, completionHandler: @escaping (Int) -> Void) {
    DispatchQueue.global().async {
        // slow calculations performed here

        DispatchQueue.main.async {           
            completionHandler(result)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

对于在后台执行的工作,您可以使用不同的优先级后台队列,也可以使用自己的自定义队列或自己的操作队列.但这些细节对于手头的问题并不重要.

有意义的是,即使基础同步函数确实存在,此函数本身也不会返回任何值.相反,这个异步再现是通过completionHandler闭包传递值.因此,你会像这样使用它:

calculate(foo: "life", bar: 42) { result in
    // we can use the `result` here (e.g. update model or UI accordingly)

    print("the result is = \(result)")
}

// but don't try to use `result` here, because we get here immediately, before
// the above slow, asynchronous process is done
Run Code Online (Sandbox Code Playgroud)

(仅供参考,以上所有示例均为Swift 3.对于Swift 2.3再现,请参阅此答案的先前版本.)