質問

I have a question on how to handle a CGImageRef as a synthesized property of a class. If I define an CGImageRef with

@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:

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?

役に立ちましたか?

解決

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.


A better approach may be to use a 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.


For reference, see the specification, specifically section 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 than assign. 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.

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.)
  • typedefs marked with __attribute__((NSObject))

他のヒント

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

How about this?

@property (nonatomic, setter=setImage:) CGImageRef image;

(void)setImage:(CGImageRef)image {
    if (_image != image) {
        CGImageRelease(_image);
        _image = CGImageRetain(image);
    }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top