调用这样的东西被认为是线程安全吗?它只创建一个UIImage,没有UI更新。我找不到任何关于此的文件。
UIImage * hiResImage = [[UIImage alloc] initWithContentsOfFile:path];
仅供参考,我稍后在主线程上进行UI更新......
[imageViewForZoom performSelectorOnMainThread:@selector(setImage:) withObject:hiResImage waitUntilDone:NO];
我已经知道的事情:
[myImageView setImage:image];
)编辑:让我们看看另一种观点。 '不线程安全'是否意味着它有可能永远被阻止?或者只是意味着在开始/持续时间执行时间上没有保证。如果是后一种情况,那么在加载图像时我们会有一些“未确定的”延迟量是没有问题的。 UI更新在主线程上完成。因此,至少创建UIImage仍然可以认为是非线程安全的。
我知道这与问题没有关系,只是想指出来,因为我担心我原来的问题没有明确的答案:)
答案 0 :(得分:4)
下面的经验不是直接使用UIImage initContentsFromFile:
,而是直接使用UIImage imageWithData
,但您的问题是关于UIImage线程的安全性。
我最近不得不调试使用从[UIImage imageWithData:]
函数NSURLConnetionDelegate
调用的connectionDidFinishLoading
来使用多个后台线程下载图像的问题。由于下载的图像用于更新用户界面,因此我必须使用下面的[NSOperationQueue mainQueue] addOperationWithBlock ...
:
- (void) connection:(URLConnection*)connection didReceiveData:(NSData *) data {
[imgData appendData:data];
}
- (void) connectionDidFinishLoading:(NSURLConnection*)connection {
[NSOperationQueue mainQueue] addOperationWithBlock:^{
UIImage *img = [UIImage imageWithData:imgData];
// more code here to update the UI
}];
}
img
拥有有效图片img
始终为nil
在调试会话期间,我注意到当调试器一次一行地执行每个语句时,问题(暂时)消失了。我的理论是,在调试器步骤模式下运行不会使UIImage
处理运行imageWithData
的并发线程。因此,我认为UIImage imageWithData
(可能还有其他类似的函数)不是线程安全的。
使用@synchronized
块似乎可以解决问题
- (void) connectionDidFinishLoading:(NSURLConnection*)connection {
[NSOperationQueue mainQueue] addOperationWithBlock:^{
@synchronized(imgData) {
// Run the following in a synchronized block
UIImage *img = [UIImage imageWithData:imgData];
}
// more code here ....
}];
}
答案 1 :(得分:1)
是。在后台加载图像是相当普遍的做法,主要是如果它是远程文件,或者正在加载许多图像。是的,只在主线程上更新UI。
编辑:
由于一些有启发性的评论,我会将我的第一个回答'是'修改为'基于经验和我对UIImage线程安全的可行替代方案的评估,我认为在加载图像方面假设它是合理的。但是,每个人都有自己的意见,也许他们在这里与代码失败相关的风险太高,无法在任何情况下做出假设。'
答案 2 :(得分:0)
根据Apple的说法,答案是肯定的,从任何线程创建UIImage都是安全的:
因为图像对象是不可变的,所以你无法改变它们 创建后的属性。大多数图像属性是自动设置的 在附带的图像文件或图像数据中使用元数据。该 图像对象的不可变性也意味着它们安全 从任何线程创建和使用。