2010-11-24 10 views
0

iPad用の私のアプリケーションの1つでは、json文字列を使用してリモートでdbを構築してから、コアデータに挿入するNSArrayに変換し、ipadに約600Mbの画像をドローロードします。このすべてはバックグラウンドスレッドで作成され、最初からメモリの問題が発生しています。 私は3つの異なるNSAutoreleasePoolを操作に入れ子にして問題を解決し、便利な点でそれらのそれぞれを解放します。私はエラーも漏れも警告もない。私はちょうどそれがそれを行うための良い方法か私は何かを欠場しているかと思っていた。ここでネストされたNSAutoreleasePool

概略的な例(実際のコードはかなり長いです):

- (void)main{ 
@try { 


    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // first pool 
    [managedOC lock]; 
    NSArray *results = [self loadEntitiesWithGroupName:@"Project" andName:@"projects"]; 
    NSAutoreleasePool *prjPool; // second pool 
    for (NSDictionary *thisResult in results) { 
     prjPool = [[NSAutoreleasePool alloc] init]; 

     Project *prj = [[Project alloc] initWithEntity:[NSEntityDescription entityForName:@"Project" inManagedObjectContext:self.managedOC] insertIntoManagedObjectContext:self.managedOC]; 
     prj.name = [thisResult objectForKey:@"name"]; 
     [prj saveThumbnail:[thisResult objectForKey:@"thumbnail"]]; 

     //Slides. Those are the images that take so mutch space. 
     NSArray *slides = [thisResult objectForKey:@"slides"]; 
     NSAutoreleasePool *slidePool; // third pool 
     if(slides != kCFNull){ 
      slidePool = [[NSAutoreleasePool alloc] init]; 
      for(NSDictionary *slide in slides){ 
       Slide *thisSlide = [[Slide alloc] initWithEntity:[NSEntityDescription entityForName:@"Slide" inManagedObjectContext:self.managedOC] insertIntoManagedObjectContext: self.managedOC]; 
       thisSlide.path = prj.path; 
       [thisSlide saveFile:[slide objectForKey:@"file"]]; 
       [prj addSlidesObject:thisSlide]; 
       [thisSlide release]; 
       [slidePool drain]; 
      } 
     } 

     [prj release]; 
     [result release]; 
     [prjPool drain]; 


    } 

    [self.managedOC unlock]; 
    [totResult release]; 
    [pool drain]; 
} 
@catch (NSException * e) { 

} 
+0

どこで、どのようにあなたが実際に画像をダウンロードしてください – Vladimir

+0

これは[thisSlide saveFile:[slide objectForKey:@ "file"]]で行われ、ダウンロードしたファイルからUIImageを作成し、NSDataとNSFileManagerを使用してアプリケーションのDocumentsフォルダに保存します。 – cescofry

答えて

1

私はあなたのコードがクラッシュしていない驚いています。 1つのオブジェクトだけがslidesコレクション内にある場合を除き-drainは、参照カウント環境で-releaseと同様に動作するので、リリース上に次のプール

slidePool = [[NSAutoreleasePool alloc] init]; // this is in the wrong place 
for(NSDictionary *slide in slides){ 
    Slide *thisSlide = [[Slide alloc] initWithEntity:[NSEntityDescription entityForName:@"Slide" inManagedObjectContext:self.managedOC] insertIntoManagedObjectContext: self.managedOC]; 
    thisSlide.path = prj.path; 
    [thisSlide saveFile:[slide objectForKey:@"file"]]; 
    [prj addSlidesObject:thisSlide]; 
    [thisSlide release]; 
    [slidePool drain]; 
} 

。あなたはこれが必要です:

for(NSDictionary *slide in slides){ 

    slidePool = [[NSAutoreleasePool alloc] init]; // this is in the right place 

    Slide *thisSlide = [[Slide alloc] initWithEntity:[NSEntityDescription entityForName:@"Slide" inManagedObjectContext:self.managedOC] insertIntoManagedObjectContext: self.managedOC]; 
    thisSlide.path = prj.path; 
    [thisSlide saveFile:[slide objectForKey:@"file"]]; 
    [prj addSlidesObject:thisSlide]; 
    [thisSlide release]; 
    [slidePool drain]; 
} 

これ以外の一般的な考え方があります。

例外が発生した場合、それはスキップされないように、あなたは、すなわちあなたがこれを行う必要があり、あなたの例外ハンドラのfinallyブロックであなたの最も外側のプールを排出する必要があります

- (void)main{ 

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // first pool 

    @try { 

     // Do al your stuff 
    } 
    @catch (NSException * e) { 

    } 
    @finally 
    { 
     [pool drain]; 
    } 
} 
+0

実際には、slidePoolの位置について正しいですが、コードは決してクラッシュしません。 @finallyビットもありがとうございます。 とにかく、いくつかのネストされた自動解放プールのアプリケーションを正しく実行しましたか? – cescofry

+0

@cescofry:はい、slidePoolのallocの場所が間違っていても問題ありません。 – JeremyP