2011-02-08 79 views
1

我想导入一个大型数据集(~6,000)到我的核心数据应用程序。我读过Apple文档“Efficiently Importing Data”,我想我正确设置了它。奇怪的是,应用程序在模拟器中没有崩溃,但是如果我使用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]; 
     } 
+1

[池漏]末尾缺失 – Felix 2011-02-08 17:59:14

+0

正确 - 我刚刚添加,但不应该影响实际导入。导入过程中仍然存在一些错误。 – nlutterman 2011-02-08 18:15:53

回答

0

我在代码中看不到任何狡猾的东西。绝对不会出现在日志中的错误?

另外一个在核心数据pdf中介绍的用于导入数据的其他优化技巧是将谓词创建移到循环外并使用替换变量。

0

我看不到任何明显的渗漏,但:

  1. 你可以尽量减少内存alloc init retain -ing使用量的NSLocaleNSDateFormatterNSNumberFormatter然后release后的-ing他们循环完成。这些在循环的运行之间似乎没有改变。

  2. 我不知道Core Data,但是NSManagedObject/Player *player对象在哪里发布?这是通过核心数据自动发布的吗?

  3. 顺便说一句,你可以使用[list lastObject]而不是[list count][list objectAtIndex:0]作为最后的两人将崩溃,如果名单是零

更新基于响应:

如果没有出现做出那么下一步就是简化代码以删除任何错误来源。

  1. 在上面#1中执行我的建议,以尽量减少循环中的代码量。

  2. 检查您是否在某处释放了list对象,或者它是否被分配为autorelease。

  3. 删除中间保存(count == LOOP_LIMIT中的所有代码),只有在处理完所有阵列后才保存并清空池。您也不应该需要以下代码if (count != 0)

  4. 用适当的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]); 
    } 
    

    }

  5. 然后检查日志,看看你得到任何奇怪的消息。您也可以在核心数据中的任何位置使用类似的代码来检查错误(即executeFetchRequest)。值得一试,找出错误在这里。

+0

NSManagedObject播放器应该与我相信的池一起发布。不幸的是它仍然崩溃,我不知道为什么。 – nlutterman 2011-02-09 21:08:37