具有核心数据和API请求的多线程

时间:2016-09-23 12:57:51

标签: ios objective-c multithreading core-data

简介

我已经阅读了很多关于Core Data并发性的教程和文章,但是我遇到的问题并不常见,或者是以我希望有人可以提供帮助的实际方式覆盖。我已经在SO中检查了相关问题,没有人给出我能找到的这个特定问题的答案。

背景

我们有一个现有的应用程序,它从API(后台线程)中获取数据,然后将返回的记录保存到核心数据中。我们还需要在应用程序中显示这些记录。

因此,我们目前正在进行的过程是:

  1. 发布数据网络请求(背景)
  2. 解析数据并将对象映射到NSManagedObjects并保存(背景)
  3. 在完成处理程序(主线程)中,我们从核心数据中获取记录,其顺序和限制与我们从API请求的顺序和限制相同。
  4. 关于核心数据并发的大多数教程遵循这种在一个线程中保存然后在另一个线程中获取的模式,但大多数都提供了如下示例:

    NSArray *listOfPeople = ...;
    [NSManagedObjectHelper saveDataInBackgroundWithContext:^(NSManagedObjectContext *localContext){
        for (NSDictionary *personInfo in listOfPeople)
        {
            PersonEntity *person = [PersonEntity createInContext:localContext];
            [person setValuesForKeysWithDictionary:personInfo];
        }
    } completion:^{
        self.people = [PersonEntity findAll];
    }];
    

    Source

    因此,无论您获得多少记录,都可以获取所有内容。这适用于小型数据集,但我希望更高效。我已多次阅读不跨线程读取/写入数据,因此之后获取可以解决此问题,但我不想获取所有内容,我只想要新记录。

    我的问题

    所以,对于我的真实世界的例子。我想向我的API发出请求以获取最新信息(可能比核心数据中最早的记录更早),并保存它们,我需要从主线程中的API返回的确切数据,以备显示。

    所以我的问题是,当我到达完成处理程序时,我如何知道要获取什么?或者API返回了什么?到目前为止我考虑过几种方法:

    1. 保存每条记录后,将ID存储在临时数组中,然后在id IN array_of_ids中执行一些提取。
    2. 如果我要求提供最新记录,我可以使用返回的记录数,然后使用命令并将我的请求限制为最新的x记录。
    3. 我的问题

      我意识到以上问题可以回答我自己的问题,但我想知道是否有更好的方法,或者这些方法中的一种比其他方法更好用?我只是觉得我错过了什么

      由于

      修改

      下面的答案实际上都没有解决这个问题,这与在后台获取和保存数据然后在主线程中使用返回的数据有关。我知道在线程之间传递数据不是一个好主意,因此常见的方法是在插入后从核心数据中获取。我想找出更有效的方法。

2 个答案:

答案 0 :(得分:0)

您检查了NSFetchedResultsController吗?您将以类似的方式使用获取的控制器,而不是将呈现的对象提取到数组中。通过NSFetchedResultsControllerDelegate,您将收到有关在后台执行的所有更改的通知(添加,删除,更改行),并且不需要手动跟踪。

答案 1 :(得分:0)

我觉得你错过了两个同时进行API调用的情况。 storring id和计数创建的enities都不适用于那种情况。考虑为每个PersonEntity添加timestamp属性。 假设您的意图是显示最近更新的人员。 要显示的最旧时间戳的加速可以如下所示:

@property NSDate *lastViewRefreshTime;
@property NSDate *oldestEntityToDisplay;
(...)
if (self.lastViewRefreshTime.timeIntervalSinceNow < -3) {
        self.oldestEntityToDisplay = self.lastViewRefreshTime;
    }
self.lastViewRefreshTime = [NSDate date];
[self displayPersonsAddedAfter: self.oldestEntityToDisplay];

现在,如果两个API响应在短于3秒的时间内返回,则它们的数据将一起显示。