2011-02-08 4 views
1

다음 기능을 사용하여 UITableViewCell에 이미지를로드 중입니다. 하지만 내 UITableView을 스크롤 할 때마다 디버거로 앱을 실행하면 [pool release]에 오류가 발생합니다. 이 문제를 해결하려면 어떻게해야합니까? 미리 감사드립니다.메모리 누출 문제

- (void) loadImage{ 

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

    imageURL = [imageURL stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];  
    //NSLog(@"img url cell**** %@",imageURL); 
    self.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]]; 
    //self.image = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]; 

    [pool release]; 
} 
+0

왜이 방법에서 자동 복구 풀을 사용하고 있습니까? 일반적으로 자신의 풀을 임의로 생성하여 릴리스하지 않아야합니다. –

+0

NSAutoReleasePool을 추가 한 이유는 다음과 같습니다._NSAutoreleaseNoPool() : UIImage 클래스의 Object 0x364d6b0이 noore 풀에서 자동으로 풀어졌습니다. 그냥 누출 된 것 같습니다. – Madhumitha

+0

풀이 main.m 파일에서 어떻게 처리되었는지보고 suggst합니다. 같은 방식으로하고 있습니다. 어딘가에 실종 된 풀 배수구가 있습니다. –

답변

0

우선 [수영장 해제] 대신 [수영장 배수구]를 사용하는 것이 좋습니다. 하지만 여기에 또 다른 잠재적 인 문제가 있습니다. 코드에 따르면 처음에 새로 만든 autorelease 풀 외부에서 imageURL을 정의했습니다 (imageURL에 대한 alloc/init가 없는데, 이는 어디에서 왔습니까?) 그런 다음 새로 할당되고 자동으로 해제 된 문자열 [imageURL stringByAddingPercentEscapesUsingEncoding : ...]으로 imageURL을 재 할당합니다. 마지막으로 풀을 풀면 새로운 imageURL이 릴리스되므로 마지막에 이전에 할당 된 imageURL의 누출이 있습니다. 이 시점에서 안쪽 autorelease 풀에서 빠져 나오면 run 루프 autorelease가 다시 imageURL을 해제하려고 시도 할 것이라고 기대할 수 있습니다 (예 : 완전히 이해하려면 코드를보아야 함). 할당 취소되었습니다.

stringByAddingPercentEscapesUsingEncoding :의 결과를 다른 이름 (예 : myImageURL)에 할당 할 수 있습니까?

+0

이 답변을 "유용하지 않음"으로 표시 한 주석 :이 코드를 실행하고 작동하는지 알려주십시오. NSString * mystr; - (void) test { \t NSLog (@ "Mystr = % @", mystr); } - (BOOL) 애플리케이션 (UIApplication *) 애플리케이션 didFinishLaunchingWithOptions : (NSDictionary와 *) launchOptions { \t \t mystr =있는 NSString stringWithString "AA"@]; \t NSAutoreleasePool * p = [[NSAutoreleasePool alloc] init]; \t mystr = [mystr stringByAppendingString : @ "BB"]; \t [p 릴리스]; \t \t [self performSelector : @selector (test) withObject : nil afterDelay : 1.0]; } 다음 별도의 스레드로 – viggio24

5

NSAutoreleasePool을 사용하고 있다는 사실 때문에로드 이미지가 주 스레드가 아닌 스레드에서 실행되고있는 것 같습니다. 이 올바른지? 이 경우 메인이 아닌 스레드에서 UIKit 호출 (self.image = ...)을 수행하고 있으며 이는 사용자가 겪고있는 충돌의 원인 일 수 있습니다. UIKit은 스레드로부터 안전하지 않으므로 모든 UIKit 업데이트는 기본 스레드에서 수행해야합니다. 교체하십시오 :

self.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]]; 

공지 사항

[self performSelectorOnMainThread:@selector(setImage:) withObject:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]] waitUntilDone:YES]; 

에 의해 내가 세터의 이름을 추측하고있어 setImage이다, 당신은 세터의 선택은 다른 이름이있는 경우 수정해야 할 수도 있습니다.

+0

예 .I 호출하고 loadImage을 mystr2하는 BB를 [P 해제]를 삭제하거나 지정하여 다시 시도 ([NSThread detachNewThreadSelector : @selector (loadImage) toTarget : 자기 withObject : 전무]). 그래서 별도의 @selector (setImage :) 코드를 작성해야합니다 ..? – Madhumitha

+0

이미지를 설정하는 방법을 만들거나 @synthesize로 만든 이미지를 사용할 수 있습니다. @synthesize는 각 속성에 대한 getter 및 setter 메서드를 만듭니다 (사용자가 지정하지 않는 한). 이름 충돌에주의하십시오. @synthesize는 setImage를 만듭니다. 따라서 속성을 설정하기위한 고유 한 메서드를 만드는 경우 setImage :라는 이름을 지정하지 않거나 @property 정의에서 "setter"를 정의하십시오. – fsaint

+0

performSelectorOnMainThread : 호출에 대해 - (void) mySetImage : (UIImage *) im {self.image = im}을 정의하고이 선택기 (@selector (mySetImage :))를 사용하십시오. – fsaint

0

여기 몇 가지 사실이 잘못되었습니다.

첫째, 자동 풀 풀이 필요하다는 것은 주 스레드에서이 작업을 수행하지 않는다는 것을 분명히 암시합니다. UIKit은 스레드로부터 안전하지 않습니다. 모든 UI 작업은 주 스레드에서 수행해야하며 충돌과 같은 정의되지 않은 동작이 발생합니다.

둘째, 이미지의 동기 URL 다운로드와 비슷한 모양을 사용하고 있습니다. 디스크의 파일 URL에서로드하는 경우이를 수정하십시오. 동기 이미지 다운로드는 UI를 올바르게 차단했기 때문에 이것을 별도의 스레드로 옮긴 이유 일 수 있습니다. 주 스레드에서 동기 API를 사용하지 않기 위해 네트워크 액세스에 대해 알아야 할 첫 번째 사항 중 하나입니다. 비동기 다운로드를 수행하기 위해 NSURLConnection 클래스를 살펴 보셨습니까?

셋째, 이미지 다운로드가 셀 디스플레이에 직접 연결되지 않도록 다시 설계해야합니다.

테이블 셀을 표시하려면 나머지 UI와 함께 주 스레드에서 수행해야합니다. 셀이 표시되면 비동기 적으로 이미지를 다운로드해야합니다. 이미지 다운로드가 캐시되어야하며 이미지 다운로드가 완료되면 델리게이트 콜백을 통해 셀에 정보를 제공해야합니다. 그런 다음 이미지를 표시해야합니다.

NSOperation에 이러한 종류의 데이터를 래핑하고 NSOperationQueue을 사용하여 데이터를 관리 할 수 ​​있습니다. 이 클래스에 대한 문서를보고 사용법을 배우려면 예제 코드를 확인하십시오.