如何有效地获取托管对象&索引作为字典的关键属性?

时间:2012-03-07 22:09:00

标签: objective-c core-data nsfetchrequest

所以,我有一个应用程序,我从Web服务导入一些数据并更新我的本地模型以匹配。来自Web服务的实体具有唯一标识属性,我正在使用它来确定是创建新的本地对象还是获取和更新现有对象。

我知道我不想循环输入并运行NSFetchRequest搜索每个项目的uniqueID匹配,因为获取请求很昂贵。相反,我汇总输入中的所有uniqueID(使用-[NSArray valueForKey:]轻松完成)并使用IN谓词获取所有可能存在的对象。

然后,我遍历输入 - 对于每个项目,我检查我刚刚进行的提取是否包含具有匹配唯一ID的对象。如果是,我用输入中的新值更新该对象;否则我会创建一个新对象。

这是匹配,我不知道如何有效地做。获取请求获取一个数组,因此我需要搜索它以找到与当前输入项的唯一ID匹配的对象。现在我正在使用-[NSArray filteredArrayUsingPredicate:] ...所以我为每个导入的项目再次搜索数组(对于我知道的对象)。

似乎更简洁有效的方法是将获取请求结果作为字典,将唯一ID(即在谓词中搜索的属性)作为键,将相应的NSManagedObjects作为值。我可以从结果数组中设置这样的字典,但这也需要重复搜索结果数组。

如果套件提供类似的东西,我找不到多少运气。有人遇到过一个好方法吗?

3 个答案:

答案 0 :(得分:0)

除了使用数组之外,您可以使用NSDictionary,而不是使用uniqueID作为键值。

答案 1 :(得分:0)

一个简单的起点可能看起来像:

NSArray *remoteObjects = // Array of dictionaries sorted by remotePrimarKey
NSArray *localObjects  = // Sorted by remotePrimaryKey using [NSPredicate predicateWithFormat:@"%@", remoteKeys];

NSInteger localIndex  = 0;
NSInteger localCount  = [localObjects count];

MyManagedObject *localObject;

for (NSDictionary *remoteObject in remoteObjects) {

  localObject = nil;

  if (localIndex < localCount) {
    localObject = [localObjects objectAtIndex:localIndex];
  }

  if (<# localObject.primaryKey == remoteObject.primaryKey #>) {
    localIndex++;
  } else {
    localObject = // create new instance of MyManagedObject
  }

  // Configure localObject here
}

有很多东西你可以改变并优化,但这是我在浏览器中写的最清楚

用简单的英语

设置

  • 获取由remotePrimaryKey排序并限制为远程数组中的键的本地对象
  • 确保远程阵列按相同的remotePrimaryKey
  • 排序

<强>过程

  • 一次遍历远程阵列一个对象
    • 如果有本地对象的话
      • 增加本地数组的索引变量
      • 配置此本地返回的对象
    • 如果找不到本地对象
      • 创建新对象
      • 配置此新本地对象

答案 2 :(得分:0)

好的,我现在感到愚蠢。我非常专注于使用我已经拥有的uniqueID数组(并在我的获取请求中使用),我忘记了我可以向后工作。

所以,这是一般大纲:

  1. 读入远程对象(词典数组)。

  2. 从中提取一系列uniqueIDs(使用valueForKey:作为循环并从每个字典objectForKey:填充数组的简写

  3. 使用所述数组和IN谓词来获取可能存在的本地对象。

  4. 使用结果数组上的valueForKey:获取与获取结果相对应的uniqueID数组。

  5. 使用+[NSDictionary dictionaryWithObjects:forKeys:]获取将uniqueID映射到本地NSManagedObjects的字典。

  6. 循环访问远程对象,查询该字典以确定每个字体是否具有需要更新的相应本地对象,或者我们需要为其创建新的本地对象。

  7. 在(简化)代码中:

    NSArray *remoteObjects; // array of dictionaries read in from server
    NSArray *remoteIDs = [remoteObjects valueForKey:@"uniqueID"];
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:myEntityName];
    request.predicate = [NSPredicate predicateWithFormat:@"uniqueID IN %@", remoteIDs];
    NSArray *results = [context executeFetchRequest:request error:NULL];
    NSArray *existingIDs = [results valueForKey:@"uniqueID"];
    NSDictionary *existingObjects = [NSDictionary dictionaryWithObjects:results forKeys:existingIDs];
    for (NSDictionary *remoteObject in remoteObjects) {
        MyManagedObject *existingObject = [existingObjects objectForKey:[remoteObject valueForKey:@"uniqueID"]];
        if (existingObject) {
            // have matching local object already, update it
        } else {
            // create new local object
        }
    }