在 Swift/Objective-C 开发中,有三种简单且完全期望的方法来解决这个问题,并且这些解决方案都不涉及直接返回值的方法。您可以编写等待异步部分完成(阻塞线程)然后返回值的代码,在某些情况下,这是在 Apple 自己的一些库中完成的,但我不打算介绍这种方法,因为这真的不是一个好主意。
第一种方法涉及完成块。
当我们的方法要执行一些异步代码时,我们可以传入一个代码块,以便在异步工作完成时执行。这样的方法看起来像这样:
func asynchStuff(completionHandler: ([String:String]) -> Void) {
// do asynchronous stuff, building a [String:String]
let result: [String: String] = // the result we got async
completionHandler(result)
}
请记住调用被调用completionHandler()
的同一线程asynchStuff
。(这个例子没有证明这一点。)
第二种方法涉及委托和协议。
我们需要一个类来完成异步工作。此类将持有对我们的委托的引用,该委托将实现完成方法。首先,一个协议:
@objc protocol AsyncDelegate {
func complete(result: [String:String]
}
现在我们的异步工作者:
class AsyncWorker {
weak var delegate: AsyncDelegate?
func doAsyncWork() {
// like before, do async work...
let result: [String: String] = // the result we got async
self.delegate?.complete(result)
}
}
记住要确定我们在调用的同一线程上调用完成委托方法doAsyncWork()
。(这个例子没有证明这一点。)
第三种方法可以使用NSNotificationCenter
. 这是适当方法的时候将非常罕见,以至于我什至不会像其他两个示例那样为一个基本示例而烦恼,因为您几乎肯定应该使用前两个示例中的一个每个场景。
您使用哪种方法完全取决于您的特定用例。在 Objective-C 中,我经常更喜欢委托而不是基于块的方法(尽管有时块是正确的),但是 Swift 允许我们将常规函数/方法作为我们的块参数传递,所以它让我稍微倾向于使用 Swift 的基于块的方法,但是,一如既往地为正确的工作使用正确的工具。
我想扩展此答案以解决在适当线程上调用回调(无论是块还是委托)的问题。我不确定是否还有办法用 GCD 做到这一点,但我们可以用NSOperationQueue
s.
func asyncStuff(completionHandler: ([String:String]) -> Void) {
let currentQueue = NSOperationQueue.currentQueue()
someObject.doItsAsyncStuff(someArg, completion: {
result: [String:String] in
currentQueue.addOperationWithBlock() {
completionHandler(result)
}
}
}