在后台线程中加载UIImage会导致ImageIO错误 [英] Loading UIImage in background thread causes ImageIO error

查看:308
本文介绍了在后台线程中加载UIImage会导致ImageIO错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个iOS项目,从后台线程中的URL加载UIImage,并将其显示在水平分页的滚动视图中。这种行为应该模仿iPhone的本机照片库应用程序。我有一个方法,我相信应该工作,但在绘制UIImages在主UI图形上下文中,我偶尔看到这个消息打印在控制台:

I am working on an iOS project that loads UIImages from URLs in a background thread and displays them in a horizontally paged scroll view. This behavior should mimic that of the native photo library application for iPhone. I have everything setup in a way that I believe should work, but upon drawing the UIImages in the main UI graphics context, I occasionally see this message print out in the console:

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

尽管有这个错误,完美地,和图像绘制如预期。我应该忽略这个错误,还是应该改变我的方法在后台线程中加载图像?目前,我使用UIImage initWithData:方法在后台线程中加载图片:

Despite this error, it appears that the app functions perfectly fine, and that the images draw as expected. Should I simply ignore this "ERROR," or should I change my method for loading images in the background thread? Currently, I load the image in a background thread using the UIImage initWithData: method:

- (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: code>方法只保留作为一个实例变量传递的图像,后来在视图的 drawRect:方法中绘制。在 drawRect:中,我使用UIImage drawInRect:方法,它似乎是错误消息的犯罪者控制台。但是,使用 CGContextDrawImage 绘制图像的底层CGImageRef仍会导致相同的错误。完整的源代码可以在这个项目的Github存储库中找到,位于文件 ANAsyncImageView .m

My loadComplete: method simply retains the image passed as an instance variable, which is later drawn in the view's drawRect: method. In drawRect:, I am using the UIImage drawInRect: method, which appears to be the perpetrator for the error message in the console. However, drawing the image's underlying CGImageRef using CGContextDrawImage still causes the same error. The full source code can be found in this project's Github repository, in the file ANAsyncImageView.m.

编辑:我现在改变了后台线程从文件加载一个CGImage,然后回调到主线程,传递CGImageRef使用免费桥接。不幸的是,这仍然产生相同的问题,证明UIImage的 imageWithCGImage:必须在某种程度上保留对原始的CGImage的引用。查看上面链接的文件(到Github存储库)的代码:

I have now changed the background thread to load a CGImage from the file, and then callback to the main thread, passing the CGImageRef using toll-free bridging. Unfortunately, this still creates the same issue, proving to me that UIImage's imageWithCGImage: must in some way keep a reference to the original CGImage. Check out the code in the file linked above (to the Github repository) for the full code:

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。

UIKit is not a thread-safe class. Therefore, you should not call UIImage from the background.

不是创建UIImages,而是将图像文件转换为CGImageRefs。你可以将其中的一个传回主线程,并从中生成一个UIImage(你仍然可以通过将图像解压缩到后台来获益)。

Rather than create UIImages, render your images files into CGImageRefs. You can pass one of these back to the main thread and generate a UIImage from that (you will have still benefited by moving the heavy-lifting of image decompression to the background).

这篇关于在后台线程中加载UIImage会导致ImageIO错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆