1

내 응용 프로그램은 애니메이션에서 많은 크기 조정 이미지를 사용합니다. 프레임을 건너 뛰지 않으려면 애니메이션을 실행하기 전에 내 이미지의 크기를 조절하고 저장하십시오. 다음은 이미지를 저장하는 코드입니다.UIImagePNGRepresentation으로 이미지를 저장할 때 메모리 문제가 발생했습니다.

+ (void)saveImage:(UIImage *)image withName:(NSString *)name { 
    NSData *data = UIImagePNGRepresentation(image); 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); 
    NSString *directory = [paths objectAtIndex:0]; 
    NSString *fullPath = [directory stringByAppendingPathComponent:name]; 
    [fileManager createFileAtPath:fullPath contents:data attributes:nil]; 

} 

불행히도이 함수를 반복적으로 호출하면 메모리에 문제가 있습니다. 10MB 정도의 이미지를 저장하려고합니다. 아마도 문제는 자동으로 변수를 변경 한 것 같습니다. 아마도 데이터를 할당하고 마지막에 릴리스해야합니다. 그러나 UIImagePNGRepresentation의 할당 버전을 찾을 수 없습니다. 누구든지 도와 줄 수 있습니까?

+0

@occulus 및 @Tommy wrt에서 v. nice 답변을 받았습니다. autoreleased vars - 그럼에도 불구하고 문제를 해결하지 않는 것, 다른 일이 원인이 될 수 있는지 궁금합니다!? – iPadDeveloper2011

+0

나는 지금 문제를 이해한다고 생각한다. 이미지를 저장할 때뿐만 아니라 이미지를 저장할 때도 자동 복구 풀이 있어야합니다. – iPadDeveloper2011

답변

1

바깥 쪽 루프는 어떤 모양입니까? 다음과 같은 경우 :

for(n = 0; n < 1000; n++) 
{ 
    ... something ... 
    [class saveImage:image withName:name]; 
} 

그런 다음 자동 풀 풀에 물건을 남겨 두는 것이 문제 일 수 있습니다. 자동 복구 풀은 호출 스택이 실행 루프로 완전히 풀릴 때만 드레인됩니다 (그렇지 않으면 자동 리턴 된 것을 리턴 결과로 사용할 수 없으므로). 당신은 아무것도 공개하지 않는 것을 감안할 때, 당신은 당신의 코드를 수정하려고 할 수 있습니다 각 그래서

+ (void)saveImage:(UIImage *)image withName:(NSString *)name { 
    // create a local autorelease pool; this one will retain objects only 
    // until we drain it 
    NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init]; 

    NSData *data = UIImagePNGRepresentation(image); 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); 
    NSString *directory = [paths objectAtIndex:0]; 
    NSString *fullPath = [directory stringByAppendingPathComponent:name]; 
    [fileManager createFileAtPath:fullPath contents:data attributes:nil]; 

    // drain the pool, which acts like release in reference counted environments 
    // but also has an effect in garbage collected environments 
    [localPool drain]; 
} 

을, 당신이 당신의 자신의 오토 릴리즈 풀을 만들 이미지의 저장. 가장 최근에 초기화 된 autorelease 풀은 자동 복구 된 모든 객체를 잡기 위해 자동으로 설정됩니다. iOS와 같은 가비지 수집 환경에서 '드레인'이라고 말하면 할당 해제되고 즉시 보유하는 모든 객체가 해제됩니다.

+0

안녕하세요, 토미. 방금 시도했지만 "프로그램 수신 신호 :"EXC_BAD_ACCESS "가 표시됩니다." 바로 오류. 데이터 및 관련 이미지를 공개하는 데 문제가있을 수 있다고 생각합니다. – iPadDeveloper2011

+0

OK, 컴파일하고 아무 것도 변경하지 않고 다시 실행 했으므로 이번에는 문제가 없습니다. – iPadDeveloper2011

+0

불행히도이 장치를 테스트 할 수 없습니다.이 문제는 "부트 스트랩 서버에 등록 할 수 없습니다 ..." 오류 : 알 수없는 오류 코드 이것은 일반적으로이 프로세스의 다른 인스턴스가 이미 실행 중이거나 디버거에 매달려 있음을 의미합니다. 프로그램 수신 신호 : "SIGABRT". " 오류. – iPadDeveloper2011

4

UIImagePNGRepresentation은 자동으로 재생 된 NSData 객체를 반환합니다. 즉, 할당 된 데이터는 가장 가까운 NSAutoreleasePool 블록을 해제 (또는 유출) 한 다음에 만 할당 해제됩니다.

루프 내에서 위의 코드를 호출하는 경우 코드가 자동으로 메모리를 자동 회수 할 수있는 가능성이 없습니다. 이러한 상황에서 NSAutoreleasePool에 전화를 걸 수 있습니다.

for (int i = 0; i < 10; i++) { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    [self saveImage:someImage withName:@"someName.png"]; 

    [pool drain]; 
} 

N.B. 이 방법으로 JPG (UIImageJPGRepresentation)를 사용하는 것과 비교하면 PNG로 작업하는 것이 매우 느립니다. 그냥 참고하시기 바랍니다.

+0

12 초 만에 나를 이길 수있어! +1. – Tommy

+0

알아, 가까운 토미! :) – occulus

+0

빠른 답장을 보내 주셔서 감사합니다! 나는 그것을 시도 할 것이다. PNG로 작업하고 있는데, 부분적으로는 투명성 구성 요소가 필요하기 때문입니다. 부분적으로는 iPhone이 'PNG'와 유사하다는 것을 이해하기 때문입니다. – iPadDeveloper2011

관련 문제