2013-03-05 3 views
1

각 페이지에 이미지가있는 페이징 된 슬라이더보기가 있습니다. 프로그램이 실행되는 동안 서버에서 이미지를 다운로드 할 수 있도록 NSOperationQueue을 사용하고 있습니다.메모리 누수 서버에서 이미지 다운로드

[self performSelectorOnMainThread:@selector(loadPic:) withObject:[NSArray arrayWithObjects:[self imageWith:[picsNames objectAtIndex:imageView.tag]], [NSString stringWithFormat:@"%d", imageView.tag], nil] waitUntilDone:YES]; 

다음 메소드를 호출 :

-(void)loadPic:(NSArray *)imageAndTagArray 
{ 
    if (imageAndTagArray.count) { 

    //loading the image to imageview 
    UIImageView *imageView = (UIImageView *)[scrollView viewWithTag:[[imageAndTagArray objectAtIndex:1] intValue]]; 
    imageView.image = [UIImage imageWithData:((NSData *)[imageAndTagArray objectAtIndex:0])]; 

    //stopping the indicator 
    [((UIActivityIndicatorView *)[imageView viewWithTag:ACTIVITY_INDICATOR_TAG]) stopAnimating]; 
} 
} 
을 scrollerview에 다운로드 한 이미지를 표시 할 수 NSOperationQueue 다음 메소드를 호출하는

-(NSData *)imageWith:(NSString *)imageName 
{ 

NSString *imagePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:imageName]; 
NSData *imageData = [NSData dataWithContentsOfFile:imagePath]; 

if (!imageData) { 

    imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[[NSString stringWithFormat:@"%@/%@", picsURL,imageName] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]]]; 

    if (imageData) { 

     [imageData writeToFile:imagePath atomically:YES]; 
    } 
}  
return imageData; 
} 

을 사용하고 내가 메인 스레드를 사용

모든 것이 처음 60 개의 이미지에는 잘 작동하지만 이후에는 메모리 경고가 표시되고 약 100 개의 이미지가 지나면 앱이 다운됩니다.

나는 이것에 너무 많은 시간을 보내고 있으며 무엇을해야 할지를 알 수 없다. 나는 Instruments를 사용했고 어떤 누출도 감지하지 못했습니다. 나는 또한 Analyze를 사용했고 그 중 하나도 보여주었습니다.

편집 : 5.jpg 로컬 이미지 난 여전히 경고를 얻을 다음과 같은 정의와 방법 정의 :

나는 imageWith를 교체 할 경우

.

-(NSData *)imageWith:(NSString *)imageName 
{ 
    return UIImagePNGRepresentation([UIImage imageNamed:@"5.jpg"]); 
} 

상황에 대해 자세히 설명해 드리겠습니다.

앱이 시작되면 페이지 당 9 개의 이미지가 포함 된 페이지 된 스크롤보기가 포함 된보기가 있습니다. scrollview는 nsoperationqueue를 사용하여 imageWith : 메소드를 호출하는 이미지를로드합니다.

사용자가 두 번째보기에서 열리는 이미지 중 하나를 누르면 두 번째 이미지가 전체 이미지로 표시됩니다. 이 두 번째보기에는 첫 번째보기와 동일한 이미지가 포함되지만 전체 화면 (페이지 당 1 이미지)을 포함하는 스크롤보기도 있습니다.

두 번째보기에서 약 60 개의 이미지를로드 한 후 앱을 앞뒤로 스크롤하면 충돌이 발생합니다. 50 개의 이미지를로드 한 다음 뒤로 버튼을 누르고 첫 번째보기로 이동 한 다음 다른 이미지를 누르고 두 번째보기로 이동하여 약 10 개의 이미지를로드하면 충돌이 발생합니다.

+0

자동 참조 계산을 사용하고 있습니까? –

+0

당신은 너무 많은 기억을 지닐 수 있습니다. 이미지 뷰에서 설정 한 이미지를 해제합니까 (예 : 사용자가 스크린에서 스크롤 할 때)? – Tim

+0

예 xCode에서 자동 참조 계산을 사용하고 있습니다. 4.6 – Mona

답변

1

메모리에 너무 많은 이미지가있는 것 같습니다. 두 번째보기를 열면 모든 이미지를 두 번 복사 할 때까지 디스크에서 이미지가 다시로드됩니다.

UIImage 클래스가이 메모리 관리를 도와 줄 수 있습니다. 그 reference page에는 메모리 부족 상황에서 데이터를 제거한 다음 다시 그릴 필요가있을 때 디스크에서 파일을 다시로드 할 수있는 기능이 있다고 설명되어 있습니다. 이것은 당신의 해결책 일 것입니다.

그러나 디스크에서 NSData로 읽은 이미지를 만들 때 UIImage는 메모리를 제거하지 못할 수도 있습니다. 이미지가 단순히 디스크에 저장되었다는 것을 알지 못합니다. 데이터를 버리고 나중에 다시로드하지 마십시오.

"imageWith"메서드를 변경하여 반환하기 바로 전에 디스크의 파일 URL에서 UIImage (imageWithContentsOfFile을 통해)를 만들고 중간 NSData를 반환하지 않고 UIImage를 반환 해 봅니다. 이렇게하면 UIImage는 디스크상의 이미지 소스가 어디서 왔는지 알게되고, 메모리가 디바이스에서 제한되면 지능적으로 퍼지/다시로드 할 수있게됩니다.

+0

"너무 많은 이미지를 메모리에 보유하고있는 것 같습니다." 너는 이것에 대해 옳았다. 그래서 내가 한 것은 코드를 변경하여 그 당시에는 10 개의 uiimages 만 가지고있었습니다. 더 이상 기억 경고가 없었다. – Mona

+0

제안한대로 imageWithContentsOfFile로 변경하고 nsdata 대신 UIimage를 반환했습니다. 메모리 경고의 경우에는 아무런 차이가 없었지만, 더 효율적으로 들렸습니다. 그래서 제가 한 것입니다. – Mona

+0

도움을 주셔서 대단히 감사합니다. 당신은 저를 많이 도왔고 충분히 감사 할 수는 없습니다 :) – Mona