0

다음 방법을 사용하여 배열의 아티스트 이미지를 다운로드합니다. 나는 LastFm을 사용하여 이미지를 얻은 다음 ESCache에 저장합니다.이미지를 다운로드 할 때 메모리 문제가 발생합니다. 배열을 통해 루핑

self.imageDownloadingQueue = [[NSOperationQueue alloc] init]; 
self.imageDownloadingQueue.maxConcurrentOperationCount = 1; 

self.artworkCache = [[ESCache alloc] initWithName:@"artworkCache" error:nil]; 

NSArray *artists = // get artists using relevant framework; 

for (MPMediaItemCollection *collection in artists){ 

    [self.imageDownloadingQueue addOperationWithBlock:^{ 
     @autoreleasepool { 

      MPMediaItem *item = [collection representativeItem]; 
      NSString *artistString = [item valueForProperty:MPMediaItemPropertyAlbumArtist]; 

      BOOL isCachedImage = [self.artworkCache objectExistsForKey:artistString];; 

      if (!isCachedImage){ 

       [[LastFm sharedInstance] getInfoForArtist:artistString successHandler:^(NSDictionary *result) { 

        if ([artistString isEqualToString:[[result objectForKey:@"_params"] objectForKey:@"artist"]]) { 

         NSURL *imageURL = [result objectForKey:@"image"]; 

         if (imageURL){ 

          NSData * data = [NSData dataWithContentsOfURL:imageURL]; 
          UIImage *artistImage = [UIImage imageWithData:data]; 

          [self.artworkCache setObject:artistImage forKey:artistString]; 

          [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
           [downloadButton setTitle:artistString forState:UIControlStateNormal]; 
           [downloadButton setBackgroundImage:artistImage forState:UIControlStateNormal]; 
          }]; 
          artistImage = nil; 
         } 
         else{ 
          UIImage *newArtworkImage = // get placeholder image; 

          if (newArtworkImage != nil){ 

           [self.artworkCache setObject:newArtworkImage forKey:artistString]; 

           [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
            [downloadButton setTitle:artistString forState:UIControlStateNormal]; 
            [downloadButton setBackgroundImage:newArtworkImage forState:UIControlStateNormal]; 
           }]; 
           newArtworkImage = nil; 
          } 
         } 

        } 
        else{ 


        } 
       } failureHandler:^(NSError *error) { 

       }]; 
      } 
     } 
    }]; 
} 

내가 엑스 코드 증가 내 메모리 사용량을 볼 수있는 단지 200메가바이트을 통해, 다음과 같은 오류 내 응용 프로그램 충돌 :

그것은 처음 50 정도 예술가를 순환

2015-01-18 20:56:36.479 Mezzo[1481:39314] Received memory warning. Mezzo(1481,0x105254000) malloc: * mach_vm_map(size=147456) failed (error code=3) * error: can't allocate region *** set a breakpoint in malloc_error_break to debug

, 자신의 이미지를 (얻는다 나는 downloadButton 변경을 볼 수있다.) 그러나 그것은 충돌한다. 증가하는 메모리 사용 문제를 어떻게 처리해야할지 모르겠습니다. 이미지를 저장 한 후 이미지를 nil으로 설정하고 모든 내용을 autoreleasepool에 넣습니다.

이 배열을 통해 반복되는 메모리 사용량을 어떻게 줄일 수 있습니까? 어떤 도움이라도 대단히 감사 할 것입니다. 감사.

답변

1
  1. 한 번에 모든 이미지를 메모리에로드하는 패턴은 문제를 일으킬 수 있습니다. 영구 저장소로 직접 스트리밍하십시오. 그런 다음 UI에서 필요에 따라 이미지보기 (및 캐시)에로드하십시오.

  2. UI가 무엇인지 (즉, 모든 이미지보기가 현재 표시되는지 또는 스크롤보기 또는 이와 유사한 정보를 채우고 있는지 여부)가 분명하지 않습니다. 주어진 시간에 볼 수 있어야하는 이미지 만 메모리에로드하십시오. 콜렉션 뷰나 테이블 뷰를 사용하면 매우 간단합니다. 스크롤보기를 수동으로 채우는 경우 어떤 작업을 통해 화면을 스크롤할지 등을 결정해야합니다.

  3. 캐시가 UIApplicationDidReceiveMemoryWarningNotification으로 등록되고 캐시가 비어 있는지 확인하십시오. 기억력에 따라. 캐시는 UI의 속도를 최적화하는 메커니즘으로 간단히 사용되어야하지만 메모리가 부족하면 캐시가 삭제되고 UI가 영구 저장소에서 이미지를 검색해야합니다. 따라서 UI는 캐시에 있는지 여부를 확인해야합니다. 그렇다면 캐시를 사용합니다. 그렇지 않다면 영구 저장소에 있는지 확인하고, 그렇다면 캐시를 프로세스의 캐시로로드하십시오. 캐시 또는 영구 저장소에서 발견되지 않는 경우에만 네트워크에서 캐시를 검색합니다.

  4. 이미지가 UI에서 요구하는 것보다 높은 해상도를 유지합니까? 예를 들어, 버튼이 44 x 44 pt이고 화면 크기가 2 인 경우 이미지 크기를 88 x 88 픽셀로 조정하십시오. 해상도 이미지를 화면에 표시하려면 resize them이면 메모리 영향을 크게 줄일 수 있습니다.

  5. 그런데 이러한 메모리 문제를 해결하면 maxConcurrentOperationCount1으로 다시 평가할 수 있습니다. 이는 심각한 성능 저하를 초래합니다. 일반적으로 4 또는 5를 권합니다. 그러나 메모리 문제를 해결할 때까지이 문제를 해결하지 마십시오.

    비동기 다운로드를 수행하는 경우이 내용이 maxConcurrentOperationCount1의 의도를 무효화했기를 바랍니다. 동시성의 정도를 제한하려면 이러한 작업을 비동기식 NSOperation 하위 클래스 (및 비동기 다운로드가 완료 될 때까지 작업을 완료하지 않는 구현)로 래핑해야합니다.

+0

자세한 답변을 보내 주셔서 감사합니다. Rob! didReceiveMemoryWarning에서 캐시를 지우지 만 많은 도움이되지 않았으므로 SDWebImage를 사용하여 이미지를 다운로드했으며 이제는 완벽하게 작동합니다! 확실하지 않은 무엇이 그러나 .... – BadBoolean

관련 문제