UIImage setImage非常慢

8

我正在尝试使用以下代码从本地URL加载图像:

UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:fileURL]];
[self.imageView setImage:image];
NSLog(@"imageView set");

我在控制台中看到 "imageView set" 的输出几乎是立即的,但它会花费很长时间才能在用户界面中反映出来(有时需要几分钟!)。

你有什么想法,为什么会发生这种情况呢?


fileURL 的值是什么?这个线程在运行什么? - Tim
你的图片是什么尺寸、文件大小和文件格式? - Raptor
fileURL 是文档目录中的 gif 文件。图像文件大小小于 1-2mb。该函数由 IBAction 触发,但我假设它在主线程上运行? - Andy Hin
我开发了一个“懒惰的UIImageView”用于异步图像下载,它可以解决你的问题。你可以从这里下载它。 - Dipen Panchasara
它可以在服务器或本地运行。 - Dipen Panchasara
显示剩余3条评论
4个回答

10

当我在后台线程中(我正在下载图像文件)设置图像时,就发生了这种情况。确保您的代码在主线程中运行即可。图像将立即更改。

// In a background thread...

UIImage *image = ... // Build or download the image

dispatch_async(dispatch_get_main_queue(), ^{ 
    [self.imageView setImage:image]; // Run in main thread (UI thread)
});

4
你应该加载工具并查看它正在做什么。
首先,你应该尽可能避免在绘图线程上进行I/O。此外,在同一时间是否有其他I/O请求? UIImage不一定需要是单个位图表示形式--它可以由缓存和/或懒加载支持。因此,仅仅因为一个'图像'已经被'设置',并不意味着最佳位图已经被加载到内存中并准备好渲染--直到请求渲染(绘制)时才会延迟加载。
另一方面,性能分析将告诉您(通常)为什么它比预期的时间更长。

谢谢。我一定要这样做。页面中唯一的其他事情就是从远程URL播放视频。 - Andy Hin
@AndyHin 如果那些沉重的视频内容是同步执行并在主线程上执行的话,它可能会阻塞绘图(“冻结”应用程序),直到视频准备好为止。 “设置”图像不会立即显示它--它只是说“此视图需要绘制,在下一个绘制周期中绘制”--但是在主线程上进行大量工作或IO可能会阻塞该视图图形重新执行,因为线程正在读取文件、下载视频或许多其他事情,这些都会阻止主线程向前移动。 - justin

-1

从NSData加载图像需要更多时间。 相反,您可以简单地使用以下代码:

UIImage *image = [UIImage imageWithContentsOfFile:fileURL];

试一下。


你是认真的吗,真的吗?O.o - holex

-2

所以我尝试了以下方法:

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:fileURL]];
    [self.imageView setImage:image];
    NSLog(@"imageView set");
});

而且速度快了很多。不过我不确定原因。


4
由于你现在正在后台线程上进行UI更新,这会使情况变得更糟且不稳定。 - rmaddy
2
你尝试过使用dispatch_get_main_queue吗?你说加载本地图像有时需要几分钟,这通常表明在使用UIKit类时意外地在后台线程上运行。 - omz
@omz 谢谢。我尝试使用dispatch_get_main_queue而不是原来的方法,速度实际上更快了。所以这似乎解决了问题。当IBAction触发一个函数时,它是在UI线程上执行的吗? - Andy Hin
1
通常情况下,当您在操作中添加此日志时,会得到什么?NSLog(@"%i", [NSThread isMainThread]); - omz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接