我正在尝试将大型数据集(~6,000)导入到我的核心数据应用程序中。我已经阅读了Apple文档“有效导入数据”,我认为我正确设置了它。奇怪的是应用程序没有在模拟器中崩溃,虽然如果我使用Leaks仪器运行它,但它没有保存所有数据。有时它只会节省3-4百倍,它将节省3-4千,很少整个数据集。我认为它可能与内存泄漏有关,我对使用NSAutoReleasePool很新,任何帮助都会非常感激。
NSURL *url = [NSURL URLWithString:@""];
NSString *responseString = [NSString stringWithContentsOfURL:url encoding:NSASCIIStringEncoding error:nil];
if (responseString) {
NSArray *players = [responseString componentsSeparatedByString:@";"];
NSUInteger LOOP_LIMIT = 100, count = 0;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSManagedObjectContext *context = [[AppController sharedAppController] managedObjectContext];
[context setUndoManager:nil];
for (int i=0; i<([players count] - 1); i++) {
NSArray *info = [[players objectAtIndex:i] componentsSeparatedByString:@","];
NSString *dateInfo = [info objectAtIndex:10];
NSLocale *usLocale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"] autorelease];
NSDateFormatter *fo = [[[NSDateFormatter alloc] init] autorelease];
[fo setDateFormat:@"MM/dd/yyyy"];
[fo setLocale:usLocale];
[fo setTimeZone:[NSTimeZone systemTimeZone]];
NSDate *dob = [fo dateFromString:dateInfo];
Players *player = [NSEntityDescription insertNewObjectForEntityForName:@"Players"
inManagedObjectContext:context];
NSNumberFormatter *f = [[[NSNumberFormatter alloc] init] autorelease];
[f setNumberStyle:NSNumberFormatterNoStyle];
player.playerID = [f numberFromString:[info objectAtIndex:0]];
player.lastName = [info objectAtIndex:1];
player.firstName = [info objectAtIndex:2];
player.position = [info objectAtIndex:4];
NSString *teamName = [info objectAtIndex:3];
NSFetchRequest *req = [[[NSFetchRequest alloc] init] autorelease];
NSEntityDescription *ent = [NSEntityDescription entityForName:@"Teams" inManagedObjectContext:context];
[req setEntity:ent];
[req setIncludesPropertyValues:NO];
NSPredicate *pre = [NSPredicate predicateWithFormat:@"team=%@", teamName];
[req setPredicate:pre];
NSArray *list = [context executeFetchRequest:req error:nil];
if ([list count]) {
Teams *team = [list objectAtIndex:0];
player.team_Players_Teams = team;
}
count++;
if (count == LOOP_LIMIT) {
[context save:nil];
[context reset];
[pool drain];
pool = [[NSAutoreleasePool alloc] init];
count = 0;
}
}
if (count != 0) {
NSLog(@"In Save Remaining");
[context save:nil];
[context reset];[pool drain];
}
答案 0 :(得分:0)
我看不到任何明显的泄漏但是:
您可以最小化alloc init retain
NSLocale
,NSDateFormatter
,NSNumberFormatter
然后release
使用的内存量循环完成后。这些似乎在循环运行之间没有变化。
我不知道核心数据,但NSManagedObject
/ Player *player
对象的释放位置在哪里?这是通过Core Data自动释放的吗?
另外,您可以使用[list lastObject]
而不是[list count]
和[list objectAtIndex:0]
,因为如果列表为零,最后两个会崩溃
根据回复更新:
如果没有任何结果可以产生影响,那么下一步就是简化代码,以便删除任何错误来源。
在上面的#1中执行我的建议,以尽量减少循环中的代码量。
检查您是否在某处释放list
对象,或者将其分配为自动释放。
删除中间保存(count == LOOP_LIMIT
内的所有代码),只有在处理完所有数组后才保存并排空池。您也不应该在if (count != 0)
将error:nil
语句替换为正确的error:&&error
并记录错误。要记录错误,请执行以下操作(道歉但代码格式似乎不起作用 - 不明白为什么):
NSError *error = nil; //Declared upfront
// Your streamlined code
// ....
error = nil; //Just before a fetchRequest or context:save
/* After looping through all your code now attempt to save */
if(![context save:&error]) {
NSLog(@"Failed to save to data store: %@", [error localizedDescription]);
NSArray *detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
if(detailedErrors != nil && [detailedErrors count] > 0) {
for(NSError *detailedError in detailedErrors) {
NSLog(@"DetailedError: %@", [detailedError userInfo]);
}
} else {
NSLog(@" %@", [error userInfo]);
}
}
然后检查日志以查看您是否收到任何奇怪的消息。您还可以在核心数据中的任何位置使用类似的代码来检查错误(即executeFetchRequest
)。值得一试,找出错误在这里。
答案 1 :(得分:0)
我在代码中也看不到任何狡猾的东西。绝对没有错误出现在日志中?
用于导入数据的Core Data pdf中涵盖的另一个优化提示是将谓词创建移出循环并使用替换变量。