保存250 MB数据后iPad应用程序崩溃

时间:2013-02-14 04:51:05

标签: iphone ios ipad

我在我的iPad应用程序中同步来自服务器的大约5000张图像。这些图像的大小约为2.5 GB,我的iPad也有足够的空间。

但在同步仅375张图片后,我的应用程序开始崩溃,原因如下

malloc: *** mmap(size=1048576) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug

2013-02-14 06:20:50.058 AAA[1250:907] ***

Terminating app due to uncaught exception 'NSMallocException',
 reason: 'Attempt to allocate 1048576 bytes for NS/CFData failed'

*** First throw call stack:

我正在使用核心数据在文档目录中保存图像。

如果对申请保存数据有任何限制,请指导我。我正在主线上执行所有这些操作。

 for (int i = 0; i < [shadowElement3 count]; i++)
        {
            NSMutableArray* array = [[NSMutableArray alloc] init];
            Product* failedBankInfo = [NSEntityDescription insertNewObjectForEntityForName:@"Product"                                                                    inManagedObjectContext:context];

            NSXMLElement* element11    = [shadowElement3 objectAtIndex:i];
            NSString* strPath = [element11 stringValueForNode:@"B1_COD"];

            NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
            NSString *documentsDirectory = [paths objectAtIndex:0];
            NSString *savedImagePath = [documentsDirectory stringByAppendingPathComponent:strPath];

            NSLog(@"%@",[element11 stringValueForNode:@"img"]);
            NSData* receivedData = [NSData dataWithContentsOfURL:[NSURL URLWithString:              [element11 stringValueForNode:@"img"]]];
            [receivedData writeToFile:savedImagePath atomically:YES];

            [array addObject:savedImagePath];

}

2 个答案:

答案 0 :(得分:4)

您可能需要使用自动释放pool。根据该文档,“如果你编写一个创建许多临时对象的循环。”

答案 1 :(得分:4)

有几件事:

  1. 您似乎每次都通过循环重新创建数组。
  2. 看起来你正在创建许多自动释放的对象。鉴于您可能正在创建几千个,您可能希望将它们包装在@autoreleasepool块中。
  3. 每次循环时都会重新创建几个变量,这些变量似乎是相同的。将它们拉出循环。
  4. 将上下文的撤消管理器设置为nil。这有助于减少内存开销。
  5. 最后,我不确定你是否在主线程上执行此操作,但如果数据连接速度较慢,dataWithContentsOfURL将阻塞主线程。您可能希望确保从主线程执行此操作。这是另一个问题的主题。
  6. 您可能希望使用enumerateObjectsUsingBlock:而不是for / loop。有关原因,请参阅here
  7. 尝试以下内容:

    NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity:[shadowElement3 count]];
    NSXMLElement* element11;
    NSString* strPath;
    NSString *savedImagePath;
    Product* failedBankInfo;
    
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    
    [context setUndoManager:nil];
    
    for (int i = 0; i < [shadowElement3 count]; i++)
    {
    
       @autoreleasepool{
          failedBankInfo = [NSEntityDescription insertNewObjectForEntityForName:@"Product"                                                                    inManagedObjectContext:context];
          element11 = [shadowElement3 objectAtIndex:i];
          strPath = [element11 stringValueForNode:@"B1_COD"];
          savedImagePath= [documentsDirectory stringByAppendingPathComponent:strPath];
    
          NSData* receivedData = [NSData dataWithContentsOfURL:[NSURL URLWithString:                       [element11 stringValueForNode:@"img"]]];
          [receivedData writeToFile:savedImagePath atomically:YES];
          [array addObject:savedImagePath];
    
          // you don't seem to be doing anything with the Managed Object you created,
          // I assume you are saving the path.  So do so and batch save the context.
          // This will help free up memory.
          failedBankInfo.pathName = savedImagePath;
          if ( i % 100 ==0 ){
              NSError *error;
              [context performBlock:^{
    
                 [context save:&error];
                 // handle error
    
                 // reset the context cause you don't seem to be doing anything else
                 // with the objects.  This will free up memory
                 [context reset];
              }];
          }
      }
    
    }
    
    // One last save
    NSError *error;
    [context performBlock:^{
        [context save:&error];
        // handle error is exercise for the reader.
    
        // reset the context cause you don't seem to be doing anything else
        // with the objects.  This will free up memory
        [context reset];
    }];
    

    祝你好运。