3

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];

}

4

2 に答える 2

4

Autoreleaseプールの使用が必要になる場合があります。ドキュメントによると、「多くの一時オブジェクトを作成するループを記述した場合。」

于 2013-02-14T05:57:42.360 に答える
4

いくつかのこと:

  1. ループのたびに配列を再作成しているようです。
  2. 多くの自動解放オブジェクトを作成しているようです。数千を作成する可能性があることを考えると、それらを @autoreleasepool ブロッ​​クでラップすることができます。
  3. 同じように見えるループを介して毎回再作成している変数がいくつかあります。それらをループから引き出します。
  4. コンテキストの元に戻すマネージャーを nil に設定します。これにより、メモリのオーバーヘッドを削減できます。
  5. 最後に、これをメイン スレッドで実行しているかどうかはわかりませんが、データ接続が遅い場合、dataWithContentsOfURL はメイン スレッドをブロックします。これをメイン スレッドから実行していることを確認したい場合があります。それは別の質問のトピックです。
  6. enumerateObjectsUsingBlock:for/loop ではなく、使用したい場合があります。理由はこちらをご覧ください。

これに沿って何かを試してください:

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];
}];

幸運を。

于 2013-02-14T06:25:49.480 に答える