I’ve got a CCLayer where I want to add many buttons.
I created the class MyButton with this init function:
-(id) initWithLayer:(MyLayer *)theLayer andDictionary:(NSDictionary *)data {
self = [super init];
if (self != nil)
{
self.layer = theLayer;
self.tag = [[data objectForKey:@"day"] intValue];
_layerZ = [[data objectForKey:@"z"] intValue];
_closedCard = [[CCSprite alloc] initWithFile:[data objectForKey:@"file"]];
_openedCardFile = [[NSString alloc] initWithString:[data objectForKey:@"open_card"]];
CCMenuItemImage *itemImage = [CCMenuItemImage
itemFromNormalSprite:_closedCard
selectedSprite:nil
target:self
selector:@selector(displayCard:)];
CGPoint position = CGPointFromString([data objectForKey:@"position"]);
_position = ccp(position.x, position.y);
itemImage.position = _position;
itemImage.tag = self.tag;
_theCardButton = [CCMenu menuWithItems:itemImage, nil];
_theCardButton.position = CGPointZero;
[self.layer addChild:_theCardButton z:_layerZ];
}
return self;
}
This init function will add the buttons to the layer and I’m managing all the behaviour (movements, image changes) in the MyButton class.
So the layer is being sent to all the MyButton instances. The layer won’t call the dealloc method until each button is released.
These buttons are being added to the layer through an array:
_buttons = [[NSMutableArray alloc] init];
for (NSDictionary *buttonData in buttonsArray) {
MyButton *btn = [[MyButton alloc] initWithLayer:self andDictionary:buttonData];
[_buttons addObject:btn];
[btn release];
}
My problem is that when I replace this scene, the dealloc methos of MyButton is not being called and the memory is not being released, cause the [_buttons release] is in the dealloc method of the layer, which is not being called either, cause the layer has been passed to each button.
It’s a mess. Can anyone tell me the best way for fixing this memory problem?
— edit
If I try to release the array of buttons manually before calling the replaceScene, each button calls the dealloc, but then I get this error message:
[CCMenu pauseSchedulerAndActions]: message sent to deallocated instance 0x131a0670
Do you retain the layer in your
initWithLayer:andDictionary:method? Then you have a retain cycle.When you send
retainmessage to an object, you increase its retain count by 1. When you sendreleasemessage, you decrease retain count by 1.deallocmessage is sent to object when its retain count reaches 0.When
releasemessage is sent to your layer, its retain count does not reach 0, because every one of_buttonsretained it for itself. Because layer’s retain count never reaches 0, itsdeallocis never called and buttons never get a release message, never get theirdealloccalled, never release the layer and so on. Cycle.To avoid retain cycles, a child object must never retain any of its parents, or any of parents’ parents.