关于 CGColor/definition
About CGColor/definition
在 class 中,我有一个 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;
我一开始以为它们是等价的,但它们不是。
我知道它们不等价,因为当我使用第一个时,我的程序可以运行。当我使用第二个时,它稍后会崩溃。在这里显示更多代码与问题完全无关。
谁能解释一下区别?这有望让我修改我的代码并能够使用第二行。
仅供参考,它崩溃于 (with: Thread 1: EXC_BAD_ACCESS (code=1, address=0x881b370e0)):
- (void)drawRect:(CGRect)rect
{
.......
CGContextSetStrokeColorWithColor(context,myColor); // Crash here !!!
CGContextStrokeEllipseInRect(context, rectangle);
.......
}
崩溃可能是因为您没有 myColor
对象的强引用 (属性)。你可能有 assign
属性
[UIColor orangeColor]
有效但 [UIColor colorWithRed...
无效的原因
当您使用 [UIColor orangeColor] 时,您不会创建对象;你得到它的引用,其他东西管理它的生命周期。
当您初始化一个新的 UIColor
对象时,您有责任确保它在使用时仍然有效。 "assign" 不会增加对象的引用计数; “strong”确实如此。
希望对您有所帮助
编辑
像这样清除那个属性
@property (nonatomic,strong) UIColor * myUIColor;
现在什么时候可以
这样做
myUIColor =[UIColor colorWithRed:1.000 green:0.500 blue:0.000 alpha:1.000]
当你需要 CGColor 时
myUIColor. CGColor
您正在分配给 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);
在任何一种情况下,您现在 "own" 这个引用,这意味着以后可以安全使用它,也意味着您有责任在用完后清理它,例如:
- (void)dealloc
{
CGColorRelease(myColor);
}
另见 this Apple Tech Q&A doc 几乎是同一个例子。
Core Foundation 对象(CGColorRef
是其中之一)所需的内存管理形式与旧的、ARC 之前的 ObjC 手动系统非常相似,您可以在其中增加保留计数您希望保留 ("own") 引用,然后在不再需要它有效时递减(释放)。 Apple has good docs for how to best think about this. In this case, assigning the reference to your instance variable means you want to keep it around as valid for some amount of time. Generally you retain at the point of assignment (either explicitly or by getting the reference via a Create function),然后在对象被释放时释放它。
在 class 中,我有一个 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;
我一开始以为它们是等价的,但它们不是。
我知道它们不等价,因为当我使用第一个时,我的程序可以运行。当我使用第二个时,它稍后会崩溃。在这里显示更多代码与问题完全无关。
谁能解释一下区别?这有望让我修改我的代码并能够使用第二行。
仅供参考,它崩溃于 (with: Thread 1: EXC_BAD_ACCESS (code=1, address=0x881b370e0)):
- (void)drawRect:(CGRect)rect
{
.......
CGContextSetStrokeColorWithColor(context,myColor); // Crash here !!!
CGContextStrokeEllipseInRect(context, rectangle);
.......
}
崩溃可能是因为您没有 myColor
对象的强引用 (属性)。你可能有 assign
属性
[UIColor orangeColor]
有效但 [UIColor colorWithRed...
无效的原因
当您使用 [UIColor orangeColor] 时,您不会创建对象;你得到它的引用,其他东西管理它的生命周期。
当您初始化一个新的 UIColor
对象时,您有责任确保它在使用时仍然有效。 "assign" 不会增加对象的引用计数; “strong”确实如此。
希望对您有所帮助
编辑
像这样清除那个属性
@property (nonatomic,strong) UIColor * myUIColor;
现在什么时候可以
这样做
myUIColor =[UIColor colorWithRed:1.000 green:0.500 blue:0.000 alpha:1.000]
当你需要 CGColor 时
myUIColor. CGColor
您正在分配给 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);
在任何一种情况下,您现在 "own" 这个引用,这意味着以后可以安全使用它,也意味着您有责任在用完后清理它,例如:
- (void)dealloc
{
CGColorRelease(myColor);
}
另见 this Apple Tech Q&A doc 几乎是同一个例子。
Core Foundation 对象(CGColorRef
是其中之一)所需的内存管理形式与旧的、ARC 之前的 ObjC 手动系统非常相似,您可以在其中增加保留计数您希望保留 ("own") 引用,然后在不再需要它有效时递减(释放)。 Apple has good docs for how to best think about this. In this case, assigning the reference to your instance variable means you want to keep it around as valid for some amount of time. Generally you retain at the point of assignment (either explicitly or by getting the reference via a Create function),然后在对象被释放时释放它。