我知道 Apple 官方推荐 UIKit 只在主线程中使用。但是,我也听说 UIImage 自 iOS 4.0 以来是线程安全的。我找不到任何支持这一说法的文件。
有没有人有任何信息来支持这种说法?UIImage 作为一个用于存储数据和解码图像数据的类,如果设计得当,它应该是线程安全的。
我知道 Apple 官方推荐 UIKit 只在主线程中使用。但是,我也听说 UIImage 自 iOS 4.0 以来是线程安全的。我找不到任何支持这一说法的文件。
有没有人有任何信息来支持这种说法?UIImage 作为一个用于存储数据和解码图像数据的类,如果设计得当,它应该是线程安全的。
图像对象是不可变的,因此您无法在创建后更改它们的属性。这意味着您通常在初始化时指定图像的属性或依赖图像的元数据来提供属性值。这也意味着图像对象本身可以安全地从任何线程使用。更改现有图像对象的属性的方法是使用一种可用的便捷方法来创建图像的副本,但具有您想要的自定义值。
(强调我的)
因此,至少在截至 2014 年 5 月 13 日的当前 SDK 版本中,“图像对象本身可以安全地从任何线程使用。”
确实,苹果建议在主线程上使用 UIKIt 中的元素:
注意:在大多数情况下,UIKit 类只能在应用程序的主线程中使用。对于从 UIResponder 派生的类或涉及以任何方式操作应用程序的用户界面的类尤其如此。
由于 UIImage 不是从 UIResponder 派生的,因此您实际上并没有在界面/屏幕上显示它。然后在另一个线程上对 UIImages 进行操作应该是安全的。
然而,这是基于我的经验,我还没有看到任何关于它的官方文档。
自从此处发布了较早的答案以来,Apple 似乎已经更新了他们的文档。根据最新的文档,从任何线程创建和使用 UIImage 实例都是安全的:
由于图像对象是不可变的,因此您无法在创建后更改它们的属性。大多数图像属性是使用随附图像文件或图像数据中的元数据自动设置的。图像对象的不可变特性也意味着它们可以安全地从任何线程创建和使用。
在iOS 中的新增功能:iOS 4.0发行说明中,UIKit 框架的增强包括以下内容:
在 UIKit 中绘制到图形上下文现在是线程安全的。具体来说:用于访问和操作图形上下文的例程现在可以正确处理驻留在不同线程上的上下文。字符串和图像绘制现在是线程安全的。现在可以安全地在多个线程中使用颜色和字体对象。
所以 UIImage 在 iOS 4.0 及更高版本上是线程安全的。
简而言之:UIImage 不是线程安全的,或者更好的是只在主线程上工作,正如我在调试后所经历的那样。
我希望这会有所帮助。我希望从 Apple 或更好的 UIImage 类中更清楚地了解这一点,它可以在不同的线程中呈现。应该不会太难...
编辑:经过一番研究,我发现它是“UIGraphicsGetImageFromCurrentImageContext();” 这导致了麻烦。这有点偏离主题,但也许这会有所帮助: https ://coderwall.com/p/9j5dca
感谢扎卡里·沃尔多夫斯基。
线程安全不是问题,因为任何线程都可以尝试同时(同时)访问上下文。而且,虽然这通常没问题,但在内存不足的情况下,例如 iOS 设备上的照片编辑扩展程序,访问一个上下文的两个线程可能会由于内存不足而导致应用程序崩溃。
将 Core Image 过滤器与 vImage 操作混合时会发生这种情况。两者都是线程安全的,但 ARC 不会在处理 Core Image 对象之前释放 vImage 缓冲区数据,因此您有时在内存中有两个图像副本。
因此,如果不了解线程和并发,你永远不会认为你对线程安全的了解是完整的——这对于任何关于线程安全的问题的答案都是加倍的。简而言之:正确的问题是,每当您谈论图像处理时,线程安全性如何应用于内存使用。
如果您只是在这里踢轮胎,则需要等到遇到真正的问题后再提出问题。但是,如果您正在计划下一步行动,您需要知道如何按顺序执行图像处理命令,并使用手动解除分配。您必须设计您的应用程序,以便在内存中只有一个正在处理的图像副本。永远不要依赖自动释放(线程安全与否)来为您进行调用。不起作用。