在后台线程中加载UIImage会导致ImageIO错误

我正在开发一个iOS项目,它从后台线程中的URL加载UIImages,并在水平分页滚动视图中显示它们。 此行为应该模仿iPhone的本机照片库应用程序。 我以一种我认为应该工作的方式设置所有内容,但是在主UI图形上下文中绘制UIImages时,我偶尔会在控制台中看到此消息:

ImageIO:  CGImageReadSessionGetCachedImageBlockData *** CGImageReadSessionGetCachedImageBlockData: bad readSession [0x685e590] 

尽管出现此错误,但似乎应用程序function完全正常,并且图像按预期绘制。 我应该简单地忽略这个“错误”,还是应该更改我在后台线程中加载图像的方法? 目前,我使用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:方法,它似乎是控制台中错误消息的实施者。 但是,使用CGContextDrawImage绘制图像的基础CGImageRef仍然会导致相同的错误。 完整的源代码可以在该项目的Github存储库中的ANAsyncImageView.m文件中找到 。

编辑:我现在已经更改后台线程从文件加载CGImage,然后回调到主线程,使用免费桥接传递CGImageRef。 不幸的是,这仍然会产生同样的问题,向我certificateUIImage的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); 

UIKit不是一个线程安全的类。 因此,您不应该从后台调用UIImage。

而不是创建UIImages,将您的图像文件渲染为CGImageRefs。 您可以将其中一个传递回主线程并从中生成UIImage(您仍然可以通过将图像解压缩的重复移动到背景中而获益)。