multithreading - 在返回值的函数内进行多线程处理的最佳实践,Swift

标签 multithreading swift design-patterns architectural-patterns

我有一个问题可能与实现无关,而是一个提示/最佳实践问题。

我正在使用 Swift 编写一个类,该类以 JSON 格式从在线源获取数据。我想在这个类中有特定的方法连接到在线资源并以字典类型返回结果。函数可能是这样的:

func getListFromOnline()->[String:String]{

    var resultList : [String:String]=[:]
    ...
    /*
    Some HTTP request is sent to the online source with NSURLRequest

    Then I parse the result and assign it to the resultList
    */
    ...

    return resultList
}

在这个实现中,我现在得到的是,没有多线程,resultList 显然是在 从在线源获取完成之前返回的。毫不奇怪,它会导致程序失败。

我有什么想法或技巧可以达到相反的效果吗?在这种情况下,我对多线程有点困惑,因为我想稍后从另一个类异步调用这个公共(public)方法,我知道该怎么做,但我不知道如何制作 返回参数的方法 本身具有多线程。

或者它根本与多线程无关,我在这里没有看到明显的解决方案?

最佳答案

在 Swift/Objective-C 开发中有三种简单且完全符合预期的方法来解决这个问题,这些解决方案都没有涉及直接返回值的方法。您可以编写等待异步部分完成(阻塞线程)然后返回值的代码,在某些 Apple 自己的库中有时会这样做,但我不会将介绍该方法,因为它确实不是什么好主意。


第一种方法涉及完成 block 。

当我们的方法要执行一些异步代码时,我们可以传入一个代码块,以便在异步工作完成时执行。这样的方法看起来像这样:

func asynchStuff(completionHandler: ([String:String]) -> Void) {
   // do asynchronous stuff, building a [String:String]
   let result: [String: String] = // the result we got async
   completionHandler(result)
}

请记住在调用 asynchStuff 的同一线程上调用 completionHandler()。 (这个例子没有证明这一点。)


第二种方法涉及委托(delegate)和协议(protocol)。

我们需要一个类来完成异步工作。这个类将持有对我们委托(delegate)的引用,它将实现完成方法。首先,一个协议(protocol):

@objc protocol AsyncDelegate {
    func complete(result: [String:String]
}

现在我们的异步 worker :

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() 的同一线程上调用完成委托(delegate)方法。 (这个例子没有证明这一点。)


第三种方法可以使用 NSNotificationCenter 来完成。这种合适的方法很少见,我什至不会像我做的其他两个例子那样费心去处理一个基本的例子,因为你几乎肯定会在几乎所有的时间里使用前两个例子中的一个。每个场景。


您使用哪种方法完全取决于您的具体用例。在 Objective-C 中,我经常更喜欢委托(delegate)而不是基于 block 的方法(尽管有时 block 是正确的),但是 Swift 允许我们将常规函数/方法作为我们的 block 参数传递,所以它让我稍微倾向于使用基于 block 的 Swift 方法,但仍然要一如既往地为正确的工作使用正确的工具。


我想扩展此答案以解决在适当线程上调用回调(无论是 block 还是委托(delegate))的问题。我不确定是否还有办法用 GCD 做到这一点,但我们可以用 NSOperationQueues 来做到这一点。

func asyncStuff(completionHandler: ([String:String]) -> Void) {
    let currentQueue = NSOperationQueue.currentQueue()
    someObject.doItsAsyncStuff(someArg, completion: { 
        result: [String:String] in
        currentQueue.addOperationWithBlock() {
            completionHandler(result)
        }
    }
}

关于multithreading - 在返回值的函数内进行多线程处理的最佳实践,Swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31093296/

相关文章:

Python - 是否有可能 "stop"或 "pause"一个线程

ios - swift 3 录制视频但不录制音频

swift - 如何在没有基值的情况下获得 CGFloat 的最大值?

java - Java Swing 中正确的模型- View - Controller 模式

C#.NET 4.0 并发字典 : TryRemove within a lock?

linux - 让 GNU Octave 与多核处理器一起工作。 (多线程)

swift - Xcode 搜索 Controller - 在开始时显示搜索栏 (Swift 4)

java - 实现工厂设计模式时如何避免 'instanceof'?

java - 为什么不让 StringBuilder 和 StringBuffer 实现一个公共(public)接口(interface)呢?

java - Android线程有时不启动