在类中我有一个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(代码= 1,地址= 0x881b370e0)):
- (void)drawRect:(CGRect)rect
{
.......
CGContextSetStrokeColorWithColor(context,myColor); // Crash here !!!
CGContextStrokeEllipseInRect(context, rectangle);
.......
}
崩溃是因为你可能没有强大的myColor
对象的ref(属性)。你可能有assign
财产
[UIColor orangeColor]
工作的原因,但不是[UIColor colorWithRed...
使用[UIColor orangeColor]时,不创建对象;你得到一个参考,其他东西管理它的生命周期。
当您初始化一个新的UIColor
对象时,您有责任确保它在使用时仍然有效。 “assign”不会增加对象的引用计数; “强”的确如此。
希望它有所帮助
编辑
声明这样的一个属性
@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
安全地存储在您的对象中,您需要拥有它,在您的情况下意味着明确保留您从CGColorRef
获得的UIColor
:
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手动系统非常相似,您可以在该系统中增加保留计数(“拥有”)引用,然后在不再需要它有效时递减(释放)。 Apple has good docs如何最好地考虑这一点。在这种情况下,为实例变量分配引用意味着您希望将其保持有效一段时间。通常,您保留在赋值点(显式或通过Create function获取引用),然后在释放对象时释放它。