创建UIImage线程安全吗?

时间:2012-10-07 06:01:21

标签: ios uiimage thread-safety

调用这样的东西被认为是线程安全吗?它只创建一个UIImage,没有UI更新。我找不到任何关于此的文件。

UIImage * hiResImage = [[UIImage alloc] initWithContentsOfFile:path]; 

仅供参考,我稍后在主线程上进行UI更新......

[imageViewForZoom performSelectorOnMainThread:@selector(setImage:) withObject:hiResImage waitUntilDone:NO];

我已经知道的事情:

  • 从iOS4开始,UIKit的许多绘图方法变得线程安全。请阅读here
  • 我不应该在后台线程上更新ui(例如,没有[myImageView setImage:image];

编辑:让我们看看另一种观点。 '不线程安全'是否意味着它有可能永远被阻止?或者只是意味着在开始/持续时间执行时间上没有保证。如果是后一种情况,那么在加载图像时我们会有一些“未确定的”延迟量是没有问题的。 UI更新在主线程上完成。因此,至少创建UIImage仍然可以认为是非线程安全的。

我知道这与问题没有关系,只是想指出来,因为我担心我原来的问题没有明确的答案:)

3 个答案:

答案 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
    }];
}
  • 在iOS 7.x模拟器上运行时,img拥有有效图片
  • 在iOS 7.x设备(iPod Touch)上运行时,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都是安全的:

  

因为图像对象是不可变的,所以你无法改变它们   创建后的属性。大多数图像属性是自动设置的   在附带的图像文件或图像数据中使用元数据。该   图像对象的不可变性也意味着它们安全   从任何线程创建和使用

https://developer.apple.com/reference/uikit/uiimage