2
votes

I got a GameScene class that is not a singleton instance. Hence I allocate and deallocate it every time the user chooses a new level and keep the "static"/"shared" data in a different singleton class (E.g. GameManager).

I am using ARC. I would like to understand if my approach is correct under the memory management point of view. In other words, is it enough to call "removeUnusedSpriteFrames" at cleanup? Will this remove all sprites in game-art-forLevelOne-hd.plist? Should I do something also with the CCSpriteBatchNode?

-(void) loadGameArtFileForLevelOne  //I do this in a switch but this is to simplify the reading 
{
    CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
    [frameCache addSpriteFramesWithFile:@"game-art-forLevelOne-hd.plist"];
    CCSpriteBatchNode * sharedSpriteBatchNode = [CCSpriteBatchNode batchNodeWithFile:@"game-art-forLevelOne-hd.png"];    
 }

//As dealloc is deprecated for ARC code, I prefer to remove unused sprites and texture on cleanup
-(void) cleanup
{
    [[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];     
}

I added a CCLOG call in the dealloc method of CCSpriteBatch node. When I load the GameScene and then go back to the menu I see the log of "remove unused texture" as expected but I don't see any log of the dealloc method of CCSpriteFrameCache. *!! Warning: See edit below - my mistake!!*

EDIT: Sorry, I meant I don't see any log of the dealloc method of CCSpriteBatch

This concerns me slightly as I want to "free" and remove all memory related to the Sprites for the level.

Once I understood this I will then "optimize" this bit (e.g. have one sprite sheet for each class of level - e.g. world 1 - and one sprite sheet for each background).

Any suggestion?

2
The dealloc method is not deprecated, you can still use it. Just calling [super dealloc] in dealloc is no longer allowed.LearnCocos2D

2 Answers

1
votes

EDIT:

I assume you are adding the CCSpriteBatchNode node somewhere, although the code you posted does not show it (you also mention, it happens in a switch, so I think in a completely different settings). If so, it will not be deallocated until you remove it from where you added it to.

Here, maybe, a clarification is in order.

The CCSpriteFrameCache is a cache: a piece of storage where all the sprites get in order to be readily available for reuse.

The CCSpriteBatchNode is a mechanism for improving performance in the Open GL layer in principle totally unrelated from the cache.

I understand that if you have some sprite used through a batch node still present in some layer/node/scene, than it will not be considered "unused" and will not be removed by your cleanup code. Actually, it is in use. The cached sprite will become "unused" when you remove it from all the nodes that refers to it.

As to your question:

In other words, is it enough to call "removeUnusedSpriteFrames" at cleanup?

Well, I think that it depends on your app what could be considered good cleanup. Removing unused sprites from the cache is certainly ok; but you might also do other things: unloading audio resources you loaded; removing parts of the scene that are not used (and could be reloaded if required); etc.

Hope this helps.

I don't see any log of the dealloc method of CCSpriteFrameCache.

CCSpriteFrameCache is a singleton, so it shall exist for the lifetime of the program (it could be different, but I bet this is the case):

 CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];

So, I would not be worried at the fact that the Cache is not deleted; what matters is that its content is emptied.

4
votes

you can use this..

 [[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFrames];

if you need more then use follow.

[[CCDirector sharedDirector] purgeCachedData];
[[CCTextureCache sharedTextureCache] removeAllTextures];
[CCTextureCache purgeSharedTextureCache];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFrames];
[CCSpriteFrameCache purgeSharedSpriteFrameCache];