在一个类中,我有一个 CGColorRef 类型的变量 myColor,声明如下:
@implementation MyClass
{
.......
CGColorRef myColor;
.......
这里有两行 Objective C 代码:
第一行:
myColor=[UIColor orangeColor].CGColor;
第二行:
myColor=[UIColor colorWithRed:1.000 green:0.500 blue:0.000 alpha:1.000].CGColor;
我最初期望它们是等价的,但事实并非如此。
我知道它们是不等价的,因为当我使用第一个时,我的程序可以工作。当我使用第二个时,它稍后会在路上崩溃。在这里显示更多代码与问题完全无关。
有人能解释一下区别吗?这有望让我修改我的代码并能够使用第二行。
仅供引用,它崩溃了(带有:线程 1:EXC_BAD_ACCESS (code=1, address=0x881b370e0)):
- (void)drawRectCGRect)rect
{
.......
CGContextSetStrokeColorWithColor(context,myColor); // Crash here !!!
CGContextStrokeEllipseInRect(context, rectangle);
.......
}
Best Answer-推荐答案 strong>
您正在分配给 Core Foundation 类型 CGColorRef 的实例变量。该类型不是 ObjC 对象类型,因此不受 ARC(自动内存管理)的约束,这意味着您需要手动管理其内存。
您的两个示例实际上都不正确,但是当您分配 [UIColor orangeColor].CGColor 时最初看不到崩溃的原因是幸运的巧合:橙色对象是可能是一个长期存在的单例对象,因此它的内部 CGColor 引用也是长期存在的,因此您对 ivar 的分配有效,并且稍后的访问恰好有效——但这只是一个红色(橙色? ) 鲱鱼。
您确实在另一种情况下看到崩溃,因为您在传递过程中创建的 UIColor 对象最终会立即被释放,因为它不再被使用。因此,当您稍后尝试使用它时,您从中提取并分配给您的 ivar 的 CGColorRef 值也立即无效且具有放射性。
要将 CGColorRef 安全地存储在您的对象中,您需要拥有它的所有权,这在您的情况下意味着明确保留您从 UIColor 获得的 CGColorRef :
myColor = CGColorRetain([UIColor colorWithRed:1.000 green:0.500 blue:0.000 alpha:1.000].CGColor);
或者更好的是完全绕过 UIColor ,而只使用直接为您提供具有创建所有权语义的颜色引用的函数:
myColor = CGColorCreateGenericRGB(1.0, 0.5, 0.0, 1.0);
无论哪种情况,您现在都“拥有”这个引用,这意味着以后可以安全使用,也意味着您有责任在完成后清理它,例如:
- (void)dealloc
{
CGColorRelease(myColor);
}
另见 this Apple Tech Q&A doc这几乎是同一个例子。
Core Foundation 对象(CGColorRef 就是其中之一)所需的内存管理形式与旧的、ARC ObjC 之前的手动系统非常相似,在该系统中,您在该点增加保留计数您希望保留(“拥有”)引用的位置,然后在您不再需要它有效时减少(释放)。苹果has good docs如何最好地考虑这一点。在这种情况下,将引用分配给您的实例变量意味着您希望它在一段时间内保持有效。通常,您在分配点保留(明确地或通过 Create function 获取引用),然后在对象被释放时释放它。
关于ios - 关于 CGColor/定义,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/55719382/
|