Let us say we have some code that looks like below:
@interface SomeClass : NSObject
@property (nonatomic, retain) NSString *someString;
@end
@implementation SomeClass
@synthesize someString;
-(id)init {
if (self=[super init]) {
someString = [NSString stringWithString:@"some string"];
}
return self;
}
@end
Am I supposed to release the someString property in the dealloc method of SomeClass, even if someString was set to autorelease and I never actually retained it in my init method? If so, I’d simply add [someString release] before [super dealloc] in the -release method. Correct?
Now the real issue I am having is that while using Cocos2D, I’ve reached a contradicting situation. My code looks like below:
@interface SomeLayer : CCLayer
@property (nonatomic, retain) CCSprite *someSprite;
@end
@implementation SomeLayer
@synthesize someSprite;
-(id)init {
if (self=[super init]) {
someSprite = [CCSprite spriteWithFile:@"SomeFile.png"];
[self addChild:someSprite];
}
return self;
}
@end
Now, I have added someSprite as a child to my layer SomeLayer. So, what should I do to make sure I have no memory leaks here? I could think of the following:
- Obviously, I’d think of calling
[someSprite release]inSomeLayer‘s-deallocmethod. but it gives meEXC_BAD_ACCESSin[super dealloc](the next line). Most likely because I didn’t remove the child, and the superclass tries to access the child that I just released. - I call
[self removeChild:someSprite cleanup:YES]in the-deallocmethod, which would remove the child and also release it. So I do not need to follow up with[someSprite release]. But hey, the-deallocmethod of the superclassCCNodealready does all that for me. - I do nothing. I wouldn’t override the
-deallocmethod at all. Well, this seems to work fine, but it contradicts the statement: “if you retain something, you’re supposed to release it”.
Any help on why I must release the object in case I, and why not in case II at an early stage would help save a lot of memory related issues in the long run.
Thanks
This is wrong. You are keeping a pointer to an autoreleased object that will disappear soon, and when you’ll try to use the
someStringpointer bad things will happen. You should use the accessor ([self setSomeString:…]), retain the autoreleased value (someString = [… retain]) or use a method that returns a retained value (someString = [[NSString alloc] init…]).In your real use case you should do the same with the sprite, you are getting
EXC_BAD_ACCESSbecause you over-release the sprite: you callreleasewithout ever retaining the value. Read the Cocoa Memory Management Guide, you will save yourself a lot of trouble in the long run.By the way, I think your main problem is that you think that a simple assignment to the
someStringvariable retains the assigned value. That is not the case (not without ARC, to be more precise). Assignment to the instance variable is just that, a plain assignment. If you want to go through the accessors, you have to send a message ([self setSomeString:…]) or use the dot notation (self.someString = …).