2010-11-24 4 views
0

iPad 용 응용 프로그램 중 하나에서 json 문자열을 사용하여 원격으로 db를 작성한 다음 코어 데이터에 삽입 할 NSArray로 변환 한 다음 ipad에 약 600MB의 이미지를 Donwload합니다. 이 모든 것은 배경 스레드에서 만들어지며 처음부터 메모리 문제가 발생합니다. 작업에서 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

다운로드 한 파일에서 UIImage를 만든 다음 NSData 및 NSFileManager를 사용하여 응용 프로그램 Documents 폴더에 저장합니다. [thisSlide saveFile : [slide objectForKey : @ "file"]] – cescofry

답변

1

나는 코드가 충돌하지 않습니다 놀랍군요. -drain은 레퍼런스 카운트 환경 -release와 동일하게 동작하므로 slides 컬렉션에서 단지 하나의 오브젝트가 존재하지 않는 한, 풀 버전을 통해

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

그 외의 일반적인 아이디어가 있습니다.

예외가이 작업을 수행해야 즉 발생하는 경우가 생략되지 않도록 당신은 당신의 예외 핸들러의 마지막 블록에있는 당신의 가장 바깥 쪽 풀을 배출해야합니다

- (void)main{ 

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

    @try { 

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

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

당신은 slidePool의 위치에 대해 실제로 옳았습니다. 그러나 코드는 결코 충돌하지 않았습니다. @finally 비트를 이용해 주셔서 감사합니다. 어쨌든 내가 한 것처럼 여러 중첩 autorelease 풀의 응용 프로그램을 수정 무엇입니까? – cescofry

+0

@cescofry : 예, slidePool의 alloc의 잘못된 위치를 제외하고는 괜찮습니다. – JeremyP