核心数据模式:如何通过网络变化有效地更新本地信息?

Jaa*_*nus 5 iphone performance core-data nsfetchrequest cocoa-design-patterns

我的应用程序效率低下,我想了解并修复.

我的算法是:

fetch object collection from network
for each object:
  if (corresponding locally stored object not found): -- A
    create object
    if (a nested related object locally not found): -- B
      create a related object
Run Code Online (Sandbox Code Playgroud)

我正在通过使用相关对象的键创建谓词查询来检查A行和B行,该键是我的模式的一部分.我看到A(总是)和B(如果执行分支到该部分)生成一个SQL选择,如:

2010-02-05 01:57:51.092 app[393:207] CoreData: sql: SELECT <a bunch of fields> FROM ZTABLE1 t0 WHERE  t0.ZID = ? 
2010-02-05 01:57:51.097 app[393:207] CoreData: annotation: sql connection fetch time: 0.0046s
2010-02-05 01:57:51.100 app[393:207] CoreData: annotation: total fetch execution time: 0.0074s for 0 rows.
2010-02-05 01:57:51.125 app[393:207] CoreData: sql: SELECT <a bunch of fields> FROM ZTABLE2 t0 WHERE  t0.ZID = ? 
2010-02-05 01:57:51.129 app[393:207] CoreData: annotation: sql connection fetch time: 0.0040s
2010-02-05 01:57:51.132 app[393:207] CoreData: annotation: total fetch execution time: 0.0071s for 0 rows.
Run Code Online (Sandbox Code Playgroud)

一个查询的0.0071s在3GS设备上很好,但如果你添加其中的100个,你只需要一个700毫秒的阻止程序.

在我的代码中,我正在使用帮助程序来执行这些提取:

- (MyObject *) myObjectById:(NSNumber *)myObjectId {
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[self objectEntity]]; // my entity cache    
    [fetchRequest setPredicate:[self objectPredicateById:objectId]]; // predicate cache    
    NSError *error = nil;
    NSArray *fetchedObjects = [moc executeFetchRequest:fetchRequest error:&error];
    if ([fetchedObjects count] == 1) {
        [fetchRequest release];
        return [fetchedObjects objectAtIndex:0];
    }
    [fetchRequest release];
    return nil;
}

MyObject *obj = [self myObjectById];
if (!obj) {
   // [NSEntityDescription insertNewObjectForEntityForName: ... etc
}
Run Code Online (Sandbox Code Playgroud)

我觉得这是错的,我应该以其他方式进行检查.它应该只打一次数据库,之后应该来自内存,对吧?(即使对于我知道肯定存在于本地的对象也会执行SQL,并且应该已经使用先前的查询加载到内存中.)但是,如果我只有来自外部源的myObjectId,这是我能想到的最好的.

所以,也许问题是:如果我有MyObjectId(MyObject上的Core Data int64属性),我该如何正确检查CD存储中是否存在相关的本地对象?预加载整组可能的匹配,然后谓词本地数组?

(一种可能的解决方案是将其转移到后台线程.这没关系,除非我从线程获得更改并执行[moc mergeChangesFromContextDidSaveNotification:aNotification];(通过通知从后台线程获取更改的对象),这仍然阻止.)

Jes*_*and 9

阅读"核心数据编程指南"中的"有效实现查找或创建".

基本上,您需要创建一个ID或属性数组,如名称,或者您从托管对象实体中获得的任何内容.

然后,您需要创建一个谓词,该谓词将使用此数组过滤托管对象.

[fetchRequest setPredicate:[NSPredicate predicateWithFormat: @"(objectID IN %@)", objectIDs]];
Run Code Online (Sandbox Code Playgroud)

当然,"objectIDs"可以是您可以用来识别的任何东西.它不必是NSManagedObjectID.

然后,您可以执行一次获取请求,并迭代生成的获取对象,以查找重复项.如果它不存在,请添加一个新的.

  • 这是链接http://developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html#//apple_ref/doc/uid/TP40003174 (6认同)