2012-01-22 4 views
1

백그라운드 스레드의 URL에서 UIImages를로드하고 가로로 페이징 된 스크롤보기로 표시하는 iOS 프로젝트에서 작업하고 있습니다. 이 동작은 iPhone 용 기본 사진 라이브러리 응용 프로그램과 유사합니다. 내가 일을한다고 생각하는 방식으로 모든 설정을 가지고 있지만, 주요 UI 그래픽 맥락에서 UIImages 그리기에, 나는 가끔 콘솔에서이 메시지 인쇄를 참조하십시오이 오류에도 불구하고백그라운드 스레드에서 UIImage로드 ImageIO 오류가 발생합니다.

ImageIO: <ERROR> CGImageReadSessionGetCachedImageBlockData *** CGImageReadSessionGetCachedImageBlockData: bad readSession [0x685e590] 

, 그것은 나타납니다 응용 프로그램이 완벽하게 잘 작동하고 이미지가 예상대로 그립니다. 이 "오류"를 단순히 무시해야합니까, 아니면 배경 스레드에서 이미지를로드하는 방법을 변경해야합니까? 현재 내가있는 UIImage initWithData: 방법을 사용하여 백그라운드 스레드에서 이미지를로드 :

- (void)backgroundLoadThread:(NSURL *)url { 
    @autoreleasepool { 
     NSData * imageData = [NSData dataWithContentsOfURL:url]; 
     UIImage * theImage = [[UIImage alloc] initWithData:imageData]; 
     if ([[NSThread currentThread] isCancelled]) { 
#if !__has_feature(objc_arc) 
      [theImage release]; 
#endif 
      return; 
     } 
     [self performSelectorOnMainThread:@selector(loadComplete:) 
           withObject:theImage waitUntilDone:NO]; 
    } 
} 

loadComplete: 메서드는 나중에 뷰의 drawRect: 방법에 그려지는 인스턴스 변수로 전달 된 이미지를 유지합니다. drawRect:에서 UIImage drawInRect: 메서드를 사용하고 있습니다.이 메서드는 콘솔에있는 오류 메시지의 가해자 인 것으로 보입니다. 그러나 이미지의 기본 CGImageRef를 CGContextDrawImage을 사용하여 그리면 여전히 같은 오류가 발생합니다. 전체 소스 코드는이 프로젝트의 Github 저장소 인 ANAsyncImageView.m에 있습니다.

편집 : 파일에서 CGImage를로드 한 다음 주 스레드에 콜백하고 무료 전화를 사용하여 CGImageRef를 전달하는 백그라운드 스레드를 변경했습니다. 불행하게도 이것은 여전히 ​​UIImage의 imageWithCGImage:이 어떤면에서 원래 CGImage에 대한 참조를 유지해야한다는 것을 증명하는 동일한 문제를 만듭니다. 전체 코드합니다 (Github의 저장소에) 위에 링크 된 파일의 코드를 체크 아웃 :

NSData * imageData = [NSData dataWithContentsOfURL:url]; 
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)imageData); 
CGImageRef loaded = CGImageCreateWithPNGDataProvider(provider, NULL, false, kCGRenderingIntentDefault); 
CGDataProviderRelease(provider); 

id imageObj = (id)loaded;   
[self performSelectorOnMainThread:@selector(loadComplete:) withObject:imageObj waitUntilDone:NO]; 
CGImageRelease(loaded); 
+0

스레드가 취소되었는지 여부에 관계없이 이미지를 공개해야합니까? 'performSelectorOnMainThread : withObject : waitUntilDone :'은 당신을 위해 객체를 유지하고 해제 할 것이므로, 당신이 아래에서 죽어가는 것에 대해 걱정할 필요가 없습니다. –

+0

먼저이 대답을 참조하십시오. https://stackoverflow.com/a/26562349/1084174 –

답변

6

UIKit은 스레드 안전 클래스가 아닙니다. 따라서 UIImage를 백그라운드에서 호출해서는 안됩니다.

UIImages를 만드는 대신 이미지 파일을 CGImageRefs로 렌더링하십시오. 이 중 하나를 메인 스레드로 전달하고 그로부터 UIImage를 생성 할 수 있습니다 (이미지 압축 해제를 백그라운드로 옮기는 것이 여전히 도움이됩니다).

+0

백그라운드 스레드가 CGImageRef를로드하고이를 주 스레드로 전달하여 차례대로 UIImage를 만드는 기본 스레드를 전달하도록 변경했습니다. 'imageWithCGImage :'. 같은 메시지가 여전히 콘솔에 출력됩니다. –

+0

이 경우,이 대답은 단순히 문제를 해결하지 못합니다. –

+0

기기 또는 시뮬레이터에서 실행 중이십니까? 관계없이 같은 오류가 발생합니까? – isaac

관련 문제