我正在为一个iPhone应用程序编写一段代码,该代码从服务器获取大量数据并在客户端上从中构建对象。它最终创建了大约40,000个对象。它们不会显示给用户,我只需要创建NSManagedObject的实例并将它们存储到持久存储中。
我认为这样做的唯一方法是创建单个对象,然后保存上下文,这是错误的吗?最好一次创建所有对象,然后以某种方式将它们创建并存储在某些集合或数组中后保存到上下文中?如果是这样,是否可以显示一些示例代码来说明这是如何完成的,或者指向我编写代码的方向?
对象本身是具有字符串或整数属性的相对直接的模型,并且不包含任何复杂的关系。
答案 0 :(得分:5)
在任何情况下,在插入每个对象后都不会保存,或者为可怕的表演做好准备。
以下是我在首次启动时用于填充Core Data存储库的代码。
#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];
}
也不要忘记在循环后最后一次保存。
另请注意,如果满足以下所有三个条件,则会存在导致崩溃的错误:
上述代码中的解决方法是将numUnsavedAirports
初始化为MAX_UNSAVED_AIRPORTS_BEFORE_SAVE
,以确保首次保存在第一次插入后发生。
我希望这会有所帮助。
答案 1 :(得分:3)
在每个对象之后保存会产生非常糟糕的性能。您应该每100个节省一次余额(测试将确定最佳位置),然后在用户退出时跟踪处理中的位置。
您可以在退出存储状态时获得时间,这样您就可以轻松地将您的位置存储在数据处理中(已保存100块中的5个区块)并从您上次停下的位置进行回收。
单独保存每个对象会锤击磁盘并使应用程序变慢。
答案 2 :(得分:1)
创建单个对象并保存上下文可能更好。
你有40k个物体。假设创建单个NSManagedObject需要x个时间单位。 40kx时间单位可能是可测量的。在创建对象时,用户可能出于某种原因退出应用程序;用户是不可预测的。下次您的应用启动时,您将再次完成整个过程。创建第39,999个对象是不可取的,只是让用户退出应用程序并失去所有工作。
如果你的应用是要创建每个对象并保存,你可以加快这个过程。应用程序启动并检查它是否能够在上次运行时完成任务。如果任务不完整,它可能会尝试从中断的地方继续。
单个对象创建和保存方法可能需要更长的时间才能完成,但更有可能完成任务。
就内存消耗而言,这也最大限度地减少了应用程序的内存状态。上下文不跟踪内存中的40k对象。