I have code like this:
MyClass.h
@interface MyClass : CCLayer {
}
@property (nonatomic, retain) CCSprite *spriteName; //retain count = 1
@property (nonatomic, retain) CustomClass *customVariable; //retain count = 1
@end
MyClass.m
@implementation MyClass
@synthesize spriteName;
@synthesize customVariable;
//rough init method
-(void)init
{
self.spriteName = [CCSprite spriteWithFileName:@"a.png"]; //retain count = same
self.customVariable = [[CustomClass alloc] init]; //retain count = 2
}
-(void)dealloc
{
[self.spriteName release]; //retain count = 0
self.spriteName = nil;
[self.customVariable release]; //retain count = 1?
self.customVariable = nil;
[super dealloc];
}
I have some questions about this:
1) I have a CCSprite which I’ve made into a property, however when I assigned it to [CCSprite spriteWithFileName:@"a.png"], it is an autoreleased object. But because I have @property (nonatomic, retain) CCSprite *spriteName, I have to release it yes?
2) For my customVariable, I seem to get an error when I release it in the manner above, but when I changed them to underscores, [_customVariable release]; _customVariable = nil, I get no error. Why is this and what is the difference between the two?
3) Am I releasing these objects right? I have commented in the retain count which I think I’m having trouble understanding. I know the basic if there’s an alloc or retain then I should +1 but I’m confused when it comes to properties.
So the full deal with these iVars goes as follows. The compiler silently treats your code like this:
in your code, the ‘readwrite’ and the iVar’s name are implicit (_spriteName), and the compiler generates the appropriate code. You could however have an iVar with a different name to point to the actual CCSprite. Using the self.spriteName semantic, the compiler converts that (auto-generates) the code under the hood. In you example the compiler has generated a setter and a getter for ‘self.spriteName’ (synthesized) as follows:
so when you use self.spriteName , depending on the context (lhs or rhs), the appropriate ‘hidden’ routine is called. So the line
actually invokes the generated setter above (setSpriteName). Conversely
invokes the generated getter. You are always free to use the ‘underlying’ iVar.
be very cautious however about changing _spriteName’s content or altering its life cycle, as you could accidentally create either a leak or a zombie, until you fully understand the internals. In dealloc, use
or
So finally, back to your problem with customVariable. Your code actually becomes