I have a question on how to handle a CGImageRef as a synthesized property of a class. If I define an CGImageRef with
我有一个问题,关于如何将CGImageRef作为类的合成属性来处理。如果我用CGImageRef定义
@property (nonatomic, retain) CGImageRef image;
then the compiler complains that "retain" cannot be used here. If I leave out the retain, then I assume "assign" is used instead, and I need to do the retain myself when I set the property:
然后编译器会抱怨“retain”不能在这里使用。如果我省略了retain,那么我假设用的是assign,我在设置属性时需要自己做retain:
self.image = CGImageRetain ( cgimage );
then I get an "Potential leak" warning when running Analyze. Can I safely ignore this warning? Or does the synthesize code do an implicit CGRetain anyways, even though no "retain" is specified in the property definition?
然后在运行分析时,会得到一个“潜在泄漏”警告。我能安全地忽略这个警告吗?或者,合成代码是否做隐式的CGRetain,即使在属性定义中没有指定“retain”?
3 个解决方案
#1
8
What you want to do is add an annotation to the property that the type really can be retained.
您需要做的是向属性添加一个注释,该类型实际上可以保留。
Change the property declaration to
将属性声明更改为
@property (nonatomic, retain) CGImageRef image __attribute__((NSObject));
Note that this will only generate the getters and setters for you, the instance variable itself is not ARC controlled. Specifically, this means that you must release it in dealloc
, and that you need to use proper retain and release when assigning directly to the instance variable.
注意,这只会为您生成getter和setter,实例变量本身不受ARC控制。具体地说,这意味着必须在dealloc中释放它,并且在直接分配实例变量时需要使用适当的retain和release。
A better approach may be to use a typedef
:
更好的方法可能是使用typedef:
typedef CGImageRef CGImageObject __attribute__((NSObject));
@property (nonatomic, retain) CGImageObject image;
In this case, the instance variable is controlled by ARC, and so you must not release it in dealloc
, and direct assignments to the instance variable are handled by ARC as well.
在这种情况下,实例变量由ARC控制,因此不能在dealloc中释放它,并且对实例变量的直接赋值也由ARC处理。
For reference, see the specification, specifically section 4.1.1:
请参阅规范,特别是第4.1.1节:
Applying
__attribute__((NSObject))
to a property not of retainable object pointer type has the same behavior it does outside of ARC: it requires the property type to be some sort of pointer and permits the use of modifiers other thanassign
. These modifiers only affect the synthesized getter and setter; direct accesses to the ivar (even if synthesized) still have primitive semantics, and the value in the ivar will not be automatically released during deallocation.对不属于可保存对象指针类型的属性应用__attribute__((NSObject)),其行为与在ARC之外的行为相同:它要求属性类型是某种类型的指针,并允许使用除赋值之外的修饰符。这些修饰符只影响合成的getter和setter;对ivar的直接访问(即使是合成的)仍然具有原始语义,并且在释放时不会自动释放ivar中的值。
and section 3:
第三节:
A retainable object pointer (or “retainable pointer”) is a value of a retainable object pointer type (“retainable type”). There are three kinds of retainable object pointer types:
可保留的对象指针(或“可保留指针”)是可保留对象指针类型的值(“可保存类型”)。有三种可保留的对象指针类型:
- block pointers (formed by applying the caret (
^
) declarator sigil to a function type)- 块指针(由应用插入符号(^)说明符魔符函数类型)
- Objective-C object pointers (
id
,Class
,NSFoo*
, etc.)- Objective-C对象指针(id、类、NSFoo*等)
- typedefs marked with
__attribute__((NSObject))
- typedef标有__attribute__((NSObject))
#2
1
I don't like to instruct the compiler when compiling. I think it's ugly. I'd override the methods myself.
我不喜欢在编译时指导编译器。我认为这是丑陋的。我会自己重写这些方法。
@interface MyClass : NSObject {
CGImageRef _image;
}
@property (nonatomic, assign) CGImageRef image;
@end
@implementation MyClass
- (void)setImage:(CGImageRef)i {
if(_image != i) {
CGImageRelease(_image);
_image = CGImageRetain(i);
}
}
- (CGImageRef)image {
return _image;
}
@end
#3
-1
How about this?
这个怎么样?
@property (nonatomic, setter=setImage:) CGImageRef image;
(void)setImage:(CGImageRef)image {
if (_image != image) {
CGImageRelease(_image);
_image = CGImageRetain(image);
}
}
#1
8
What you want to do is add an annotation to the property that the type really can be retained.
您需要做的是向属性添加一个注释,该类型实际上可以保留。
Change the property declaration to
将属性声明更改为
@property (nonatomic, retain) CGImageRef image __attribute__((NSObject));
Note that this will only generate the getters and setters for you, the instance variable itself is not ARC controlled. Specifically, this means that you must release it in dealloc
, and that you need to use proper retain and release when assigning directly to the instance variable.
注意,这只会为您生成getter和setter,实例变量本身不受ARC控制。具体地说,这意味着必须在dealloc中释放它,并且在直接分配实例变量时需要使用适当的retain和release。
A better approach may be to use a typedef
:
更好的方法可能是使用typedef:
typedef CGImageRef CGImageObject __attribute__((NSObject));
@property (nonatomic, retain) CGImageObject image;
In this case, the instance variable is controlled by ARC, and so you must not release it in dealloc
, and direct assignments to the instance variable are handled by ARC as well.
在这种情况下,实例变量由ARC控制,因此不能在dealloc中释放它,并且对实例变量的直接赋值也由ARC处理。
For reference, see the specification, specifically section 4.1.1:
请参阅规范,特别是第4.1.1节:
Applying
__attribute__((NSObject))
to a property not of retainable object pointer type has the same behavior it does outside of ARC: it requires the property type to be some sort of pointer and permits the use of modifiers other thanassign
. These modifiers only affect the synthesized getter and setter; direct accesses to the ivar (even if synthesized) still have primitive semantics, and the value in the ivar will not be automatically released during deallocation.对不属于可保存对象指针类型的属性应用__attribute__((NSObject)),其行为与在ARC之外的行为相同:它要求属性类型是某种类型的指针,并允许使用除赋值之外的修饰符。这些修饰符只影响合成的getter和setter;对ivar的直接访问(即使是合成的)仍然具有原始语义,并且在释放时不会自动释放ivar中的值。
and section 3:
第三节:
A retainable object pointer (or “retainable pointer”) is a value of a retainable object pointer type (“retainable type”). There are three kinds of retainable object pointer types:
可保留的对象指针(或“可保留指针”)是可保留对象指针类型的值(“可保存类型”)。有三种可保留的对象指针类型:
- block pointers (formed by applying the caret (
^
) declarator sigil to a function type)- 块指针(由应用插入符号(^)说明符魔符函数类型)
- Objective-C object pointers (
id
,Class
,NSFoo*
, etc.)- Objective-C对象指针(id、类、NSFoo*等)
- typedefs marked with
__attribute__((NSObject))
- typedef标有__attribute__((NSObject))
#2
1
I don't like to instruct the compiler when compiling. I think it's ugly. I'd override the methods myself.
我不喜欢在编译时指导编译器。我认为这是丑陋的。我会自己重写这些方法。
@interface MyClass : NSObject {
CGImageRef _image;
}
@property (nonatomic, assign) CGImageRef image;
@end
@implementation MyClass
- (void)setImage:(CGImageRef)i {
if(_image != i) {
CGImageRelease(_image);
_image = CGImageRetain(i);
}
}
- (CGImageRef)image {
return _image;
}
@end
#3
-1
How about this?
这个怎么样?
@property (nonatomic, setter=setImage:) CGImageRef image;
(void)setImage:(CGImageRef)image {
if (_image != image) {
CGImageRelease(_image);
_image = CGImageRetain(image);
}
}