Core Data 中的并发获取请求

Posted

技术标签:

【中文标题】Core Data 中的并发获取请求【英文标题】:Concurret fetch request in Core Data 【发布时间】:2016-03-01 15:56:10 【问题描述】:

我的应用正在使用 Alamofire 通过对服务器的异步请求以 JSON 格式获取数据。我需要执行以下操作: 1. 做多个 fetch 请求并接收 JSON 数据 2. 将 JSON 数据发送到我的DataImporter 类以导入 Core Data

DataImporter 类必须执行以下操作: 1. 将 JSON 转换为 NSManagedObject 的数组,用于存储到 Core Data 2.从Core Data中获取当前托管对象 3. 将转换后的对象与获取的对象进行比较,然后更新/删除/添加新对象 4.将状态保存到核心数据

以下是我认为从 ViewController 发送请求的方式:

override func viewDidLoad() 
        super.viewDidLoad()
        Alamofire.request(.GET, url1)
            .responseJSON  response in           
            switch response.result 
            case .Success(let value):
                self.dataImporter.importArticles(value)
            case .Failure(let error):
                print(error)
            
    
        Alamofire.request(.GET, url2)
            .responseJSON  response in           
            switch response.result 
            case .Success(let value):
                self.dataImporter.importArticles(value)
            case .Failure(let error):
                print(error)
            
    

这是我的 DataImporter 类的样子:

class DataImporter 

    private var privateMOC:NSManagedObjectContext!

    init () 
        privateMOC = setupManagedObjectContextWithConcurrencyType(.PrivateQueueConcurrencyType)
    

    func importArticles(articlesInJson:JSON) 
        self.privateMOC.performBlock  () -> Void in  
        let articles = self.convertJsonToArticle(articlesInJson)
        let fetchedArticles = //return articles using privateMOC
        //compare articles and delete/update/add new articles
        self.privateMOC.save()
     

现在我的问题是: 1. 这是从 Web 服务导入数据的有效方式吗? 2. 我应该为 Alamofire 请求使用不同的队列吗? 3. 我对并发 MOC 的使用是否正确?我是否需要将获取请求和导入分成两个单独的方法?

【问题讨论】:

有什么问题?没有什么不妥。试试看:D 我已经阅读了很多文章,但我把所有的事情都搞混了。我最后一次尝试将队列与核心数据一起使用最终导致出现意外错误和违反约束。现在我只需要有人确认这种方式是正确的方式。 因此,CoreData 和并发的主要内容是该线程/队列需要有一个上下文。这与不能跨线程使用核心数据对象的问题有关,而是跨线程传递它们的 managedObjectId 以便可以获取和使用它们。您还需要注意通知 UI 或其他对象有关新数据的信息。有一个 didSaveNotification,您可以在其中访问所有更改。这就是 NSFetchedResultsController 好用的原因,它可以在其监视的对象发生变化时自动更新 UI 是 fetchRequest。 【参考方案1】:
    这是从 Web 服务导入数据的有效方式吗?

是的,与 Alamofire 同时执行这些请求一样高效。

但是,有机会改进它:

如果加载的 JSON 很大并且 带宽 是限制因素,则可能有必要按顺序执行请求。这样做的效果是,第一个请求完成得更快,数据可以被第二阶段 - DataImporter - 更快地使用,并且所有后续请求都在更均匀分布的时间内完成。请注意,导入只能按顺序处理 JSON。由于托管对象的执行上下文(串行调度队列),它只能使用 一个 CPU。

如果您改为并行下载所有数据,它们可能会同时到达,但数据导入器一次只能提供 一个 数据。因此,按顺序加载它们可能会改进这种方法。

    我应该为 Alamofire 请求使用不同的队列吗?

您根本无法更改网络请求的底层工作线程。您可以设置的(可能)是将执行委托的调度队列。这个队列不应该是 main_queue。如果可以在 Alamofire 中配置,请选择全局并发队列。

    我对并发 MOC 的使用是否正确?

据我所知,是的。但是,我会在方法 importArticles 中添加一个完成处理程序,因为它是一个异步函数。

我需要将获取请求和导入分成两个单独的方法吗?

您在网络请求的完成处理程序中调用importArticles 表单 - 这完全没问题。除非您正在使用诸如 Promises 或 Futures 之类的辅助类,否则这是您必须采用的方式。

恕我直言,在您的情况下,使用公开“未来”或“承诺”的库(或任何“Rx”库)的解决方案可能会使您的代码更易于理解。它还有助于以简洁的方式实现错误处理和取消。

【讨论】:

以上是关于Core Data 中的并发获取请求的主要内容,如果未能解决你的问题,请参考以下文章

关于.Net Core 前后端分离跨域请求时 ajax并发请求导致部分无法通过验证解决办法。

使用 Core Data 等待 withTaskGroup 有时会失败

连接没有通过 Python3 异步并发 HTTP 获取请求关闭

有没有比获取请求更快的方法来检索 Core Data 中的特定托管对象?

curl实现多路并发请求(请求数量大时再次分割实现循环处理)

通过浏览器获取并发请求数