iOS4&背景[UIImage setImage:]
到iOS 3.2,我使用这种代码在后台加载 UIImageView
图像,并且效果很好...
代码:
- (void)decodeImageName:(NSString *)name
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
UIImage *newImage = [UIImage imageNamed:name];
[myImageView setImage:newImage];
[pool release];
}
...
[self performSelectorInBackground:@selector(decodeImageName:) withObject:@"ID"]
...即使 [UIImageView setImage:]
不是线程安全的!
但从 iOS 4 开始,它不再起作用了......setImage
调用后两秒图像出现在屏幕上。如果我执行 [myImageView PerformSelectorOnMainThread:@selector(setImage:) withObject:newImage waitUntilDone:YES]
而不是 [myImageView setImage:newImage]
,图像会立即出现,但看起来再次即时重新解码(忽略之前应该已经解码图像数据的 [UIImage imageNamed:]
),导致我的主线程暂停......即使文档说底层图像缓存在所有线程之间共享。。
有什么想法吗?
Up to iOS 3.2, I used this kind of code to load UIImageView
image in background, and it worked fine...
Code:
- (void)decodeImageName:(NSString *)name
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
UIImage *newImage = [UIImage imageNamed:name];
[myImageView setImage:newImage];
[pool release];
}
...
[self performSelectorInBackground:@selector(decodeImageName:) withObject:@"ID"]
... even if [UIImageView setImage:]
was not thread-safe !
But since iOS 4, it doesn't work any more... Images appear on screen two seconds after setImage
call. And if I do a [myImageView performSelectorOnMainThread:@selector(setImage:) withObject:newImage waitUntilDone:YES]
instead of [myImageView setImage:newImage]
, images appear immediately but seem to be re-decoded again on-the-fly (ignoring the previous [UIImage imageNamed:]
which should have already decoded the image data), causing a pause on my main thread... Even if documentation says The underlying image cache is shared among all threads..
Any thought ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不要在后台执行此操作!它不是线程安全的。由于
UIImageView
也是一个NSObject
,我认为使用-[performSelectorOnMainThread:withObject:waitUntilDone:]
可能会起作用,例如:它是新创建的线程安全的
UIImage
。UIImageView
仍然不是线程安全的。Don’t do it in the background! It’s not thread-safe. Since an
UIImageView
is also anNSObject
, I think that using-[performSelectorOnMainThread:withObject:waitUntilDone:]
on it might work, like:And it’s
UIImage
which is newly made thread-safe.UIImageView
is still not thread-safe.performSelectorInBackground:
在后台线程中运行选择器。然而 setImage: 是一个 UI 函数。 UI 函数只能在主线程上运行。我没有深入了解这个特定的问题,但这是对该代码的第一感觉,可能是 iOS4 以某种方式以不同的方式处理在后台线程中运行 UI 函数的(不支持的)机制。performSelectorInBackground:
runs a selector in a background thread. Yet setImage: is a UI function. UI functions should only be run on the main thread. I do not have insight into the particular problem, but this is the first gut feel about this code, and it may be that iOS4 handles the (non-supported) mechanism of running UI functions in background threads somehow differently.如果您使用的是 iOS 4.0,您确实应该考虑阅读有关块和 GCD 的内容。使用这些技术,您可以简单地将您的方法替换为:
If you're using iOS 4.0, you should really consider reading up on blocks and GCD. Using those technologies, you can simply replace your method with:
我们引用一下:
所以你也许可以只调用
image.CGImage
。我不认为 CGImages 是懒惰的。如果这不起作用,您可以使用类似
“有些人警告线程安全”之类的内容强制渲染。文档说 UIGraphics{Push,Pop,GetCurrent}Context() 仅限主线程,但没有提及任何有关
UIGraphicsBeginImageContext()
的内容。如果您担心,请使用CGBitmapContextCreate
和CGContextDrawImage
。Let's quote:
So you might be able to just call
image.CGImage
. I don't thinkCGImages
are lazy.If that doesn't work, you can force a render with something like
Some people warn about thread-safety. The docs say
UIGraphics{Push,Pop,GetCurrent}Context()
are main-thread-only but don't mention anything aboutUIGraphicsBeginImageContext()
. If you're worried, useCGBitmapContextCreate
andCGContextDrawImage
.