IT story

UIImage 이미지 해제하기

hot-time 2020. 7. 19. 09:14
반응형

UIImage 이미지 해제하기


2014 년 2 월 편집 : 이 질문은 iOS 2.0에서 시작되었습니다! 그 이후로 이미지 요구 사항과 처리 기능이 크게 발전했습니다. Retina는 이미지를 더 크게 만들고 약간 더 복잡하게로드합니다. iPad 및 retina 이미지를 기본적으로 지원하므로 코드에서 ImageNamed를 사용해야합니다 .

나는 많은 사람들 imageNamed이 나쁜 말을 하지만 성능이 좋다고 말하는 사람들의 수가 같습니다-특히 렌더링 할 때 UITableView. 참조 이 SO 질문에 예 또는 이 문서 iPhoneDeveloperTips.com에를

UIImageimageNamed방법은 누출에 사용되었으므로 피하는 것이 가장 좋았지 만 최근 릴리스에서는 수정되었습니다. 이미지를 캐시하기 위해 시스템을 신뢰할 수있는 위치와 여분의 마일을 가져 와서 직접 수행 해야하는 위치에 대한 합리적인 결정을 내리기 위해 캐싱 알고리즘을 더 잘 이해하고 싶습니다. 나의 현재 기본적인 이해는 간단한 점이다 NSMutableDictionaryUIImages파일 이름에 의해 참조. 점점 커지고 메모리가 떨어지면 훨씬 작아집니다.

예를 들어, 뒤에 이미지 캐시 imageNamed가 응답하지 않는다는 것을 누구나 알고 didReceiveMemoryWarning있습니까? 애플이 이것을하지 않을 것 같다.

캐싱 알고리즘에 대한 통찰력이 있으면 여기에 게시하십시오.


tldr : ImagedNamed가 정상입니다. 메모리를 잘 처리합니다. 그것을 사용하고 걱정하지 마십시오.

2012 년 11 월 수정 :이 질문은 iOS 2.0에서 시작되었습니다! 그 이후로 이미지 요구 사항과 처리 기능이 크게 발전했습니다. Retina는 이미지를 더 크게 만들고 약간 더 복잡하게로드합니다. iPad 및 retina 이미지를 기본적으로 지원하므로 코드에서 ImageNamed를 사용해야합니다. 자, 후손을 위해 :

Apple Dev Forums 자매 스레드 는 더 나은 트래픽을 받았습니다. 특히 Rincewind 는 일부 권한을 추가했습니다.

iPhone OS 2.x에는 메모리 경고 후에도 imageNamed : 캐시가 지워지지 않는 문제가 있습니다. 동시에 + imageNamed : 캐시 용이 아니라 편의상 많이 사용되어 문제를 이전보다 더 많이 확대했을 수 있습니다.

경고하는 동안

스피드 프론트에는 무슨 일이 일어나고 있는지에 대한 일반적인 오해가 있습니다. + imageNamed :가 수행하는 가장 큰 작업은 소스 파일에서 이미지 데이터를 디코딩하여 데이터 크기를 거의 항상 크게 늘려주는 것입니다 (예 : 화면 크기 PNG 파일은 압축시 수십 KB를 소비 할 수 있지만 MB를 절반 이상 소비 할 수 있음) 압축 해제-너비 * 높이 * 4). 반대로 + imageWithContentsOfFile :은 이미지 데이터가 필요할 때마다 해당 이미지의 압축을 해제합니다. 상상할 수 있듯이 이미지 데이터가 한 번만 필요한 경우 캐시 된 이미지 버전을 사용하고 필요한 것보다 오래 사용할 수 있다는 점을 제외하고는 아무것도 얻지 못했습니다. 그러나 자주 다시 그려야하는 큰 이미지가있는 경우 대안이 있지만 주로 권장하는 이미지는 큰 이미지를 다시 그리는 것을 피하는 것입니다. :).

캐시의 일반적인 동작과 관련하여 파일 이름을 기준으로 캐시를 수행하므로 (+ imageNamed의 두 인스턴스는 동일한 이름을 사용하면 동일한 캐시 데이터를 참조해야 함) 더 많은 이미지를 요청하면 캐시가 동적으로 커집니다 + imageNamed :. iPhone OS 2.xa 버그에서는 메모리 경고가 수신 될 때 캐시가 축소되지 않습니다.

+ imageNamed : 캐시는 iPhone OS 3.0의 메모리 경고를 존중해야합니다. 기회가있을 때 테스트하고 버그가 아닌 경우 버그를보고하십시오.

그래서 거기 있습니다. imageNamed : 창문을 부수거나 아이들을 살해하지 않습니다. 매우 간단하지만 최적화 도구입니다. 슬프게도 이름이 잘못되어 있고 사용하기 쉬운 평등 한 것이 없습니다. 따라서 사람들은 그것을 과도하게 사용하고 단순히 일을 할 때 화를냅니다.

UIImage에 범주를 추가하여 문제를 해결했습니다.

// header omitted
// Before you waste time editing this, please remember that a semi colon at the end of a method definition is valid and a matter of style.
+ (UIImage*)imageFromMainBundleFile:(NSString*)aFileName; {
    NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
    return [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@", bundlePath,aFileName]];
}

Rincewind에는 최적화 된 버전을 빌드하기위한 예제 코드도 포함되어 있습니다. 나는 그것이 주요한 가치가 있다는 것을 볼 수는 없지만 여기서는 완전성을위한 것입니다.

CGImageRef originalImage = uiImage.CGImage;
CFDataRef imageData = CGDataProviderCopyData(
     CGImageGetDataProvider(originalImage));
CGDataProviderRef imageDataProvider = CGDataProviderCreateWithCFData(imageData);
CFRelease(imageData);
CGImageRef image = CGImageCreate(
     CGImageGetWidth(originalImage),
     CGImageGetHeight(originalImage),
     CGImageGetBitsPerComponent(originalImage),
     CGImageGetBitsPerPixel(originalImage),
     CGImageGetBytesPerRow(originalImage),
     CGImageGetColorSpace(originalImage),
     CGImageGetBitmapInfo(originalImage),
     imageDataProvider,
     CGImageGetDecode(originalImage),
     CGImageGetShouldInterpolate(originalImage),
     CGImageGetRenderingIntent(originalImage));
CGDataProviderRelease(imageDataProvider);
UIImage *decompressedImage = [UIImage imageWithCGImage:image];
CGImageRelease(image);

이 코드의 단점은 디코딩 된 이미지가 더 많은 메모리를 사용하지만 렌더링 속도가 빠르다는 것입니다.


내 경험에 따르면 imageNamed로 만든 이미지 캐시가 메모리 경고에 응답하지 않습니다. mem 관리까지 얻을 수있을만큼 간결한 두 개의 응용 프로그램이 있지만 mem이 없어서 여전히 설명 할 수없는 충돌이 발생했습니다. imageNamed를 사용하여 이미지를로드하는 것을 중단하면 두 응용 프로그램이 크게 안정되었습니다.

I will admit that both applications loaded somewhat large images, but nothing that would be totally out of the ordinary. In the first application, I just skipped caching altogether because it was unlikely a user would come back to the same image twice. In the second, I built a really simple caching class doing just what you mentioned - keeping UIImages in an NSMutableDictionary and then flushing its contents if I received a memory warning. If imageNamed: were to cache like that, then I shouldn't have seen any performance upgrade. All of this was running on 2.2 - I don't know if there's any 3.0 implications on this.

You can find my other question around this issue from my first app here: StackOverflow question about UIImage cacheing

One other note - InterfaceBuilder uses imageNamed under the covers. Something to keep in mind if you do run into this problem.

참고URL : https://stackoverflow.com/questions/924740/dispelling-the-uiimage-imagenamed-fud

반응형