简体   繁体   中英

Cocos2d and iOS: how to deal with dealloc methods of static CCScene

I am using some static instance of a GameScene subclass of CCScene. Calling from GameScene

[[CCDirector sharedDirector] replaceScene:[MainMenuScene scene]]; 

doesn't trigger the dealloc method of the GameScene.

The method is called once I load again the scene (and a new GameScene is created):

+(id) sceneWithId:(int)sceneId
{
    CCScene* scene = [CCScene node];
    GameScene* gameScene = [[self alloc] initWithId:sceneId];
    [scene addChild:gameScene z:0 tag:GameSceneLayerTagGame];
    return scene;
}

-(id) initWithId:(int)sceneId
{
    CCLOG(@"scene With id");
    if ((self = [super init]))
    {
        instanceOfGameScene = self;
        //ONLY NOW the previous object becomes unreferenced and the memory management system is allowed to deallocate it

I wanted to understand if there is a way of forcing the dealloc method to be called every time I replace a (static) scene and not only when the memory gets "freed".

Or, if I should instead, write some cleanups methods that stops ongoing processes that I don't want to effect the MainMenuScene (eg I have put a stop background music method call in the dealloc method of GameScene but as also the background music is in a static class -and is not added to GameScene as child- then it keeps playing once back in the MainMenuScene).

My quick fix proposal hence is to do something like this:

    [self stopAllStuffInOtherStaticClassesThatAreRelatedOnlyToGameScene];
    [[CCDirector sharedDirector] replaceScene:[MainMenuScene scene]];

Is this a good approach?

EDIT: when is sensible to add this code in the dealloc method?

  [self removeAllChildrenWithCleanup:TRUE];

I smell bad practice. Never, ever keep a static instance of a node around. Especially not outside the scene hierarchy. It just breaks cocos2d's way of handling memory management.

If you need to preserve state, save this state to a separate class but by all means let the scene go when you change scenes. Then restore the state when the scene inits again.

You can not force the dealloc method. Wanting to do so is a sign of code smell. You can however override the -(void) cleanup method to run de-initialization code before dealloc and after the node has been removed as child.

EDIT: when is sensible to add this code in the dealloc method?

[self removeAllChildrenWithCleanup:TRUE];

Never. Ever.

Again, if you find you need to do this, there's a terrible bug somewhere. Cocos2D will have removed the child nodes by this time. In fact, it does so during the cleanup method, one way to cause cocos2d not to remove a node's children is when you override cleanup and not call [super cleanup].

Or perhaps when you keep it as a static instance, so it'll never actually call the cleanup method. And even worse would then continue to run scheduled updates and actions.

You trouble is that you don't release your game scene. Create it as

GameScene* gameScene = [[[self alloc] initWithId:sceneId] autorelease];

and it will be deallocated right.

Anyway, I don't see any need to create game scene as a child of other scene, but maybe i don't know something about your project.

And I cannot understand, what do you mean under "static CCScene"

Using 'Instruments' under Developer Tools, I was able to make some progress on this matter:

When the scene is created it should follow a few simple rules to keep the memory low:

  1. Allocate the sprites from smallest to largest
  2. Make sure to call [self unscheduleAllSelectors]; at the right times
  3. Override the -(void)dealloc method with the following code if you want to see significant memory improvements in your case, as this will hit every time the CCScene is loaded:

     // Clean up memory allocations from sprites [[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames]; [[CCDirector sharedDirector] purgeCachedData]; [[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFrames]; [CCSpriteFrameCache purgeSharedSpriteFrameCache]; 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM