为什么我的所有NSManagedObject都会立即出现故障?

时间:2012-06-23 02:19:53

标签: iphone objective-c ios cocoa-touch core-data

我正在运行一个非常基本的获取请求,它返回大约2000个对象。我正在使用一个批量大小为15的NSFetchedResultsController。

    predicate= [NSPredicate predicateWithFormat:@"ANY tags.tagName==%@", currentTagObject.tagName];
    [fetchRequest setPredicate:predicate];

    NSSortDescriptor *sort= [[NSSortDescriptor alloc] initWithKey:@"createDate" ascending:NO selector:@selector(compare:)];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
    [fetchRequest setFetchBatchSize:15];
   self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:appDelegate.managedObjectContext sectionNameKeyPath:@"createDay" cacheName:nil];

但是获取请求需要10秒以上。我启用了SQLite调试,所以我可以看到发生了什么。我认为它取得了所有2000个实体,只有15个具有实际值,然后由于某种原因经历了2000个对象中的每一个并且将它们发生故障。

在获取期间,这些行会出现数千次:

2012-06-22 21:14:47.546 app[9227:707] CoreData: annotation: sql connection fetch time: 0.0107s
2012-06-22 21:14:47.551 app[9227:707] CoreData: annotation: total fetch execution time: 0.0171s for 15 rows.
2012-06-22 21:14:47.568 app[9227:707] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZAUTHOREMAIL, t0.ZAUTHORNAME, t0.ZCREATEDATE, t0.ZISGLOBAL, t0.ZISLOCKED, t0.ZISNEW, t0.ZISPENDINGDELETE, t0.ZISPENDINGSYNC, t0.ZLASTUPDATED, t0.ZLOCALLYMODIFIEDDATE, t0.ZMETALASTUPDATED, t0.ZNOTEID, t0.ZNUMBEROFCHILDREN, t0.ZPARENTAUTHOREMAIL, t0.ZPARENTNOTEID, t0.ZROOTAUTHOREMAIL, t0.ZROOTNOTEID, t0.Z4PENDINGADDNOTES, t0.Z4PENDINGREMOVENOTES FROM ZMBNOTEOBJECT t0 WHERE  t0.Z_PK IN  (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)  ORDER BY t0.ZCREATEDATE DESC LIMIT 15
...thousands more lines exactly similar to the three above

我的表一次只显示5个单元格,所以我不知道为什么所有对象都会立即出现故障。可能是什么导致了这个?如果没有我甚至滚动我的桌子,为什么所有的对象都会立即出现故障?难道它们被某个地方访问,也许是迭代的?调用NSArray *fetchedObjects = fetchedResultsController.fetchedObjects是否会导致所有对象出现故障?

2 个答案:

答案 0 :(得分:0)

您看到的行为在Batch-faulting and Pre-fetching段落下的核心数据编程指南中有详细描述。

简而言之,如果您使用谓词来获取具有特定名称的标记的对象,则应预先获取标记对象。这是因为通常在获取对象时,Core Data不会获取相关对象,而是使用错误。现在你的谓词触发单独触发那些很慢的错误。

答案 1 :(得分:-1)

查看有关batchSize(我的重点)的文档中的内容:

  

默认值为0.批处理大小0被视为无限,这将禁用批处理错误行为。

     

如果设置非零批处理大小,则执行提取时返回的对象集合将分为批处理。执行提取时,评估整个请求并记录所有匹配对象的标识,但不会提取batchSize个对象的数据持久性商店一次。从执行请求返回的数组将是一个代理对象,它根据需要透明地对批处理进行故障处理。 (在数据库术语中,这是一个内存中的游标。)

     

您可以使用此功能限制应用程序中的工作数据集。与fetchLimit结合使用,您可以创建任意结果集的子范围。

所以,很明显,根据这个解释,你可以获得2000/15的往返商店。这肯定需要一些时间。由于您的排序和ANY谓词,您需要所有数据,但您指示请求一次只能获得15个。

另外,为了完整性,请从之前的注释中删除:从排序描述符中删除compare