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:
[someSprite release]
in SomeLayer
's -dealloc
method. but it gives me EXC_BAD_ACCESS
in [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.[self removeChild:someSprite cleanup:YES]
in the -dealloc
method, which would remove the child and also release it. So I do not need to follow up with [someSprite release]
. But hey, the -dealloc
method of the superclass CCNode
already does all that for me.-dealloc
method 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
someString = [NSString stringWithString:@"some string"];
This is wrong. You are keeping a pointer to an autoreleased object that will disappear soon, and when you’ll try to use the someString
pointer 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_ACCESS
because you over-release the sprite: you call release
without 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 someString
variable 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 = …
).