UIImage解压缩导致滚动滞后 [英] UIImage decompression causing scrolling lag

查看:88
本文介绍了UIImage解压缩导致滚动滞后的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个应用程序与全屏tableView显示一堆微小的图像。这些图像从Web中提取,在后台线程上处理,然后使用以下内容保存到磁盘:

I have this app with a full screen tableView that displays a bunch of tiny images. Those images are pulled from the web, processed on a background thread, and then saved to disk using something like:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0);
    // code that adds some glosses, shadows, etc 
    UIImage *output = UIGraphicsGetImageFromCurrentImageContext();

    NSData* cacheData = UIImagePNGRepresentation(output);
    [cacheData writeToFile:thumbPath atomically:YES];

    dispatch_async(dispatch_get_main_queue(), ^{
        self.image = output; // refreshes the cell using KVO
    });
});

此代码仅在第一次显示单元格时执行(因为之后图像已经打开)磁盘)。在这种情况下,使用以下方式加载单元格:

This code is only executed the first time the cell is displayed (since after that the image is already on disk). In that case, the cell is loaded using:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    UIImage *savedImage = [UIImage imageWithContentsOfFile:thumbPath];

    if(savedImage) {
        dispatch_async(dispatch_get_main_queue(), ^{
            self.image = savedImage; // refreshes the cell using KVO
        });
    }
});

我的问题是,在第一种情况下,滚动非常顺畅。但在第二种情况下(它直接从磁盘读取图像),即使图像加载,滚动也是超级生涩。绘图是造成滞后的因素。使用Instruments,我看到 copyImageBlockSetPNG png_read_now inflate 是占用大部分cpu(它们不是在将 self.image 分配给 UIGraphicsGetImageFromCurrentImageContext()

My problem is that in the first case, scrolling is butter smooth. But in the 2nd case (where it's reading the image directly from disk), scrolling is super jerky, even once the image is loaded. Drawing is what's causing the lag. Using Instruments, I see copyImageBlockSetPNG, png_read_now and inflate are taking up most of the cpu (they aren't when assigning self.image to UIGraphicsGetImageFromCurrentImageContext())

我假设发生了这种情况,因为在第一种情况下,UIImage是绘图的原始输出,而在第二种情况下,它必须在每次绘制时解压缩PNG。我尝试使用JPG而不是PNG,我得到了类似的结果。

I'm assuming this happens because in the first case the UIImage is a raw output of the drawing, whereas in the second case it has to decompress the PNG every time it's drawing it. I tried using JPGs instead of PNGs and I get similar results.

有没有办法解决这个问题?也许只有在它第一次被绘制时才解压缩PNG?

Is there a way to fix this? Maybe to have it only decompress the PNG the first time it gets drawn?

推荐答案

你的问题是 + imageWithContentsOfFile:是缓存和延迟加载。如果你想做这样的事情,而是在你的后台队列中使用这个代码:

Your problem is that +imageWithContentsOfFile: is cached and lazy loading. If you want to do something like this, instead use this code on your background queue:

// Assuming ARC
NSData* imageFileData = [[NSData alloc] initWithContentsOfFile:thumbPath];
UIImage* savedImage = [[UIImage alloc] initWithData:imageFileData];

// Dispatch back to main queue and set image...

现在,使用此代码,图像数据的实际解压缩仍然是懒惰的并且花费一点点,但不会像您在代码示例中使用延迟加载所获得的文件访问量那么多。

Now, with this code, the actual decompression of the image data will still be lazy and cost a little bit, but not nearly as much as the file access hit you're getting with the lazy loading in your code example.

由于您仍然遇到性能问题,您还可以强制UIImage在后台线程上解压缩图像:

Since you're still seeing a performance issue, you can also force UIImage to decompress the image on the background thread:

// Still on background, before dispatching to main
UIGraphicsBeginImageContext(CGSizeMake(100, 100)); // this isn't that important since you just want UIImage to decompress the image data before switching back to main thread
[savedImage drawAtPoint:CGPointZero];
UIGraphicsEndImageContext();

// dispatch back to main thread...

这篇关于UIImage解压缩导致滚动滞后的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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