2012-09-11 3 views
2

내 앱에서는 많은 이미지를 표시하기 위해 UIImageViewUIScrollView을 사용합니다 (약 20 개의 이미지가 있고 매번 이미지는 약 600px * 500px이고 크기는 약 600kb 임).UIImageView 및 UIScrollView는 많은 사진을로드합니다.

// Here is pictures Data; 
self.klpArry = self.pictureData; 

CGSize size = self.klpScrollView1.frame.size; 
for (int i=0; i < [klpArr count]; i++) { 
    UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake((size.width * i)+300, 20, 546, 546)]; 
    NSString *filePath = [[NSBundle mainBundle] pathForResource:[klpArr objectAtIndex:i] ofType:@"jpg"]; 
    UIImage *imageData = [[UIImage alloc]initWithData:[NSData dataWithContentsOfFile:filePath]]; 
    [iv setImage:imageData]; 
    iv.backgroundColor = [UIColor grayColor]; 
    [self.klpScrollView1 addSubview:iv]; 
    imageData = nil; 
    iv = nil; 
    iv.image = nil; 
    filePath = nil; 
    [imageData release]; 
    [filePath release]; 
    [iv release]; 
} 
    // show the picture in scrollview; 
[self.klpScrollView1 setContentSize:CGSizeMake(size.width * numImage, size.height)]; 
self.klpScrollView1.pagingEnabled = YES; 
self.klpScrollView1.showsHorizontalScrollIndicator = NO; 
self.klpScrollView1.backgroundColor = [UIColor grayColor]; 

하지만이 기능을 초기화 할 때마다, 메모리가 5메가바이트에 대해 증가 :

나는이 기능을 수행하기 위해이 코드를 사용합니다. 실제로 UIImageView, UIimageUIScrollView (vi.image=nil, [vi release])을 릴리스했지만 작동하지 않습니다. 할당 된 메모리가 해제되지 않습니다. BTW, 내 친구의 코드를 먼저 vi.image = nilvi = nil; 있지만 그림을 scrollview 표시되지 않습니다. 메모리가 관심사 인 경우

+0

나는 [이 방법] [1], 당신은 모양을 가질 수와 그것을 해결. [1] : http://stackoverflow.com/questions/10221591/how-to-optimize-uiscrollview-with-large-numbers-of-images/10274469#10274469 – Mil0R3

+0

@Veelian 당신에게 당신의 코멘트를 감사 ,이 코드를 참조하십시오. 그것을위한 어떤 데모가 있습니까 ?? – Allan

답변

3

가장 큰 문제를 검색하는 것, 내가 그것을보고, 당신이 nil에 로컬 변수를 설정하는 것입니다 그리고 당신은 그 지역을 사용하려고 진행 release과 같은 변수가 있지만 nil으로 설정되었으므로 해당 메서드는 이제 아무 것도 수행하지 않으며 +1 retainCount (또는보기에 추가 했으므로 이제는 +2)의 개체는 절대로 생성되지 않습니다. 풀어 놓았다.

따라서
//Here is pictures Data; 
self.klpArry = self.pictureData; 

CGSize size = self.klpScrollView1.frame.size; 
for (int i=0; i < [klpArr count]; i++) { 
    UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake((size.width * i)+300, 20, 546, 546)]; 
    NSString *filePath = [[NSBundle mainBundle] pathForResource:[klpArr objectAtIndex:i] ofType:@"jpg"]; 
    UIImage *imageData = [[UIImage alloc]initWithData:[NSData dataWithContentsOfFile:filePath]]; 
    [iv setImage:imageData]; 
    iv.backgroundColor = [UIColor grayColor]; 
    [self.klpScrollView1 addSubview:iv]; 

    // Don't set these to nil, or else subsequent release statements do nothing! 
    // These statements are actually not necessary because they refer to local 
    // variables so you don't need to worry about dangling pointers. Make sure 
    // you're not confusing the purpose of setting a pointer to nil in ARC to 
    // what you're doing in your non-ARC code. 
    // 
    // imageData = nil; 
    // iv = nil; 

    // You don't want to set this to nil because if iv is not nil, your image 
    // will be removed from your imageview. So, not only is this not needed, 
    // but it's undesired. 
    // 
    // iv.image = nil; 

    // This statement is not necessary for the same reason you don't do it 
    // to imageData or iv, either. This is probably even worse, though, because 
    // filePath is not a variable that you initialized via alloc. You should 
    // only be releasing things you created with alloc (or new, copy, mutableCopy, 
    // for which you issued a retain statement). 
    // 
    // filePath = nil; 

    [imageData release]; 

    // filePath is a +0 retainCount already, so don't release. You only release 
    // those items for which you increased retainCount (e.g. via new, copy, 
    // mutableCopy, or alloc or anything you manually retained). 
    // 
    // [filePath release]; 

    [iv release]; 
} 

// show the picture in scrollview; 
[self.klpScrollView1 setContentSize:CGSizeMake(size.width * numImage, size.height)]; 
self.klpScrollView1.pagingEnabled = YES; 
self.klpScrollView1.showsHorizontalScrollIndicator = NO; 
self.klpScrollView1.backgroundColor = [UIColor grayColor]; 

은, 코드를 단순화 (및 수정) 아마 될 것입니다 :

//Here is pictures Data; 
self.klpArry = self.pictureData; 

CGSize size = self.klpScrollView1.frame.size; 
for (int i=0; i < [klpArr count]; i++) { 
    UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake((size.width * i)+300, 20, 546, 546)]; 
    NSString *filePath = [[NSBundle mainBundle] pathForResource:[klpArr objectAtIndex:i] ofType:@"jpg"]; 
    UIImage *imageData = [[UIImage alloc] initWithData:[NSData dataWithContentsOfFile:filePath]]; 
    [iv setImage:imageData]; 
    iv.backgroundColor = [UIColor grayColor]; 
    [self.klpScrollView1 addSubview:iv]; 
    [imageData release]; 
    [iv release]; 
} 

// show the picture in scrollview; 
[self.klpScrollView1 setContentSize:CGSizeMake(size.width * numImage, size.height)]; 
self.klpScrollView1.pagingEnabled = YES; 
self.klpScrollView1.showsHorizontalScrollIndicator = NO; 
self.klpScrollView1.backgroundColor = [UIColor grayColor]; 

또는 당신이 더 당신의 코드를 단순화 할 수

따라서, 나는 다음을 제안 할 것

//Here is pictures Data; 
self.klpArry = self.pictureData; 

CGSize size = self.klpScrollView1.frame.size; 
for (int i=0; i < [klpArr count]; i++) { 
    UIImageView *iv = [[[UIImageView alloc] initWithFrame:CGRectMake((size.width * i)+300, 20, 546, 546)] autorelease]; 
    NSString *filePath = [[NSBundle mainBundle] pathForResource:[klpArr objectAtIndex:i] ofType:@"jpg"]; 
    UIImage *imageData = [[[UIImage alloc] initWithData:[NSData dataWithContentsOfFile:filePath]] autorelease]; 
    [iv setImage:imageData]; 
    iv.backgroundColor = [UIColor grayColor]; 
    [self.klpScrollView1 addSubview:iv]; 
} 

// show the picture in scrollview; 
[self.klpScrollView1 setContentSize:CGSizeMake(size.width * numImage, size.height)]; 
self.klpScrollView1.pagingEnabled = YES; 
self.klpScrollView1.showsHorizontalScrollIndicator = NO; 
self.klpScrollView1.backgroundColor = [UIColor grayColor]; 

길이 요, 문 (0과 : autorelease의 사용을 통해) :

UIImage *imageData = [[[UIImage alloc] initWithData:[NSData dataWithContentsOfFile:filePath]] autorelease]; 

아마로 단순화 할 수있다 :와

UIImage *imageData = [UIImage imageWithContentsOfFile:filePath]; 

이 당신에게 UIImage을 제공하는 +0 retainCount (즉, 당신은 당신의 파일에서 release 그것) 할 필요 없다. 그래서

, 몇 최종 관찰 :

  1. 당신은 정말 아마 검토하고 Advanced Memory Management Programming Guide을 연구해야한다. 메모리 관리가 처음이라면 독서량이 많지만 (특히 ARC 코드가 아닌) 이러한 개념을 숙달하는 것이 중요합니다.

  2. 당신이하지 않은 경우, 나는 정적 분석기 ("제품"- "분석"또는 변화 + 명령 + B)를 통해 코드를 실행하는 것이 좋습니다 것입니다. 분석가가 이러한 문제를 많이 (대부분은 아닐지라도) 확인하지 못했 더라면 놀랄 것입니다. 분석기를 통해 코드를 실행할 때 경고가 없어야합니다.

  3. 이 문제를 한 단계 더 높이려면 메모리 관리에 대해 훨씬 더 보수적 인 자세를 원할 수 있습니다. 통치 원리는 주어진 시간에 UI에서 필요한 이미지 만로드하는 시스템 디자인입니다. calvinBhai의 훌륭한 이미지로드 지연 제안 (UI가 까지 실제로 메모리에로드되지 않음))이 필요합니다. 또한 화면에서 스크롤하면 사전 프로 액티브 이미지가 표시됩니다. 한 번에 20 개의 이미지 만 다루기 때문에 앱에서 걱정할 필요가 없을 수도 있지만 포트폴리오/갤러리가 100 개 또는 1000 개의 이미지로 확장 된 경우 모든 이미지를 유지하는 아이디어 기억은 언제나 나쁜 생각입니다. 이것은보다 진보 된 개념이므로, 기존 코드의 기본 메모리 관리 문제에 우선 초점을 맞추어야하지만, 장기적으로는 지연로드 및 이미지의 사전 릴리스를 고려해야 할 수도 있습니다.

+1

+1 좋은 설명. 3 번을 확장하려면, 'UITableView'가 셀을 재사용하는 것처럼 스크롤 뷰의 섹션을 재사용하는 타일 된 스크롤 뷰를 살펴 본다. –

+0

@Rob 당신의 코멘트를 주셔서 감사합니다, 나는 심각한 독서 기사가 될 것입니다. – Allan

2

은 눈에 보이는 이미지, 다음 및 이전 이미지를로드 = 이미지 게으른 로딩을 시도합니다. 모든 이미지를 klpscrollview에 추가하지 않아도됩니다.

이미지를 스크롤 뷰에로드하는 것이 지연되면 스크롤 뷰에 표시되지 않는 이미지를 고칠 수 있습니다. 쉽게

는 "게으른 부하를 UIImage에있는 UIScrollView"

+0

답장을 보내 주셔서 감사합니다. 내 문제를 해결하기위한 아이디어는 없습니까? – Allan

관련 문제