2010-04-09 8 views
7

我正在研究iPhone应用程序的一段代码,它从服务器获取一堆数据并在客户端从它构建对象。它最终创建了大约40,000个对象。它们不会显示给用户,我只需要创建NSManagedObject的实例并将它们存储到持久存储中。内存高效地插入核心数据对象数组的方法

我错在认为唯一的方法来做到这一点是创建一个单一的对象,然后保存上下文?是最好一次创建对象,然后以某种方式将它们保存到上下文后创建并存储在某些集合或数组中?如果是这样,那么可以显示一些示例代码来说明这是如何完成的,或者指示我如何编写代码的位置?

对象本身是相对直接的模型,具有字符串或整数属性,并且不包含任何复杂的关系。

回答

5

在任何情况下,都不会在插入每个对象后保存,或准备好可怕的表演。

以下是我在首次启动时用于填充核心数据存储库的代码。

#define MAX_UNSAVED_AIRPORTS_BEFORE_SAVE 1000 
int numAirports = 0; 
int numUnsavedAirports = MAX_UNSAVED_AIRPORTS_BEFORE_SAVE; // *** bug. see below 
for (NSDictionary *anAirport in initialAirports) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    Airport *newAirport = [NSEntityDescription insertNewObjectForEntityForName:@"Airport" inManagedObjectContext:managedObjectContext]; 

    newAirport.city   = [anAirport objectForKey:@"city"]; 
    newAirport.code   = [anAirport objectForKey:@"code"]; 
    newAirport.name   = [anAirport objectForKey:@"name"]; 
    newAirport.country_name = [anAirport objectForKey:@"country_name"]; 
    newAirport.latitude  = [NSNumber numberWithDouble:[[anAirport objectForKey:@"latitude"] doubleValue]]; 
    newAirport.longitude = [NSNumber numberWithDouble:[[anAirport objectForKey:@"longitude"] doubleValue]]; 
    newAirport.altitude  = [NSNumber numberWithDouble:[[anAirport objectForKey:@"altitude"] doubleValue]]; 

    numAirports++; 
    numUnsavedAirports++; 
    if (numUnsavedAirports >= MAX_UNSAVED_AIRPORTS_BEFORE_SAVE) { 
     if (![managedObjectContext save:&error]) { 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
      abort(); 
     } 
     numUnsavedAirports = 0; 
    } 
    [pool release]; 
} 

另外不要忘记在循环后最后一次保存一次。

另外要注意,一个bug的存在,将导致崩溃,如果所有三个下列条件都满足:

  1. 资源库是空的
  2. 你有段一个UITableView
  3. 你首先保存保存多个对象。

在上面的代码的解决方法是初始化numUnsavedAirportsMAX_UNSAVED_AIRPORTS_BEFORE_SAVE为了确保第一插入后的第一个保存情况。

我希望这会有所帮助。

1

创建单个对象并保存上下文可能会更好。

您有40k个对象。假设创建一个NSManagedObject需要x个时间单位。 40kx时间单位可能是可测量的。在创建对象时,用户可能因某种原因退出应用程序;用户是不可预知的。下次您的应用程序启动后,您将再次完成整个过程。创建第39,999个对象仅仅是为了让用户退出应用程序并失去所有这些工作并不可取。

如果您的应用程序要创建每个对象并保存,则可以加快此过程的速度。应用程序启动并检查它是否能够在上次运行时完成任务。如果任务不完整,它可能会尝试提取停止的地方。

单个对象的创建和保存方法可能需要较长时间才能完成,但完成该任务的可能性较大。

就内存消耗而言,这也可以最大限度地减少应用程序的内存状态。上下文不跟踪内存中的40k对象。

+2

分别保存每个对象会产生可怕的表现。 – 2010-04-10 00:27:20

3

在每个对象之后保存会产生非常差的性能。您应该每隔100次就会有一次保存的平衡(测试将确定最佳位置),然后在用户退出时跟踪处理过程中的位置。

您可以在退出时获得存储状态的时间,以便您可以轻松地在数据处理中存储您的位置(保存5个块),然后从您离开的位置重新找回。

单独保存每个对象都会敲击磁盘并减慢应用程序的爬行速度。

+0

除了这个正确的建议之外,还应考虑在保存后重置ManagedObjectContext以减少内存占用量。但请注意,重置上下文会使您在此环境中失去任何中间结果。例如。批量获取结果也消失了。 – Bjinse 2013-02-19 08:59:03

+0

相关的Apple文档位于:https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html – Bjinse 2013-02-19 09:08:03