Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cocos2D project with many scenes does not release memory properly

I've got a great problem and I don't understand very well why occurs. This is the case:

  • Have a great project in Cocos2D with 10 scenes. Each scenes is a page of a book with huge sprites. It uses Kobold2D 1.0.2 implementation.
  • Every page has common objects in a singleton class, to put a common menus via LayerColor.
  • The sprites is TexturePacker in PVR.CCZ RGBA4444 and in iPad memory are around 16-20Mb every spritesheet loaded.
  • I use CCTransitionTurnPage for replaceScene for one to the next one.
  • At init method of each page (class), load the texture and FrameFile.
  • At onExit method of each page (class), unload the textures and frameFile. I used the dumpCachedTextureInfo and says me textures load and unload from memory perfectly.
  • Of course, I remove from child all objects. All my sprites are common variables declared on the interface section at .h, because I need to access them in every method of the class.
  • My project is made with Kobold2D integration in a ARC project (but you know the attached Kobold2D project has ARC not enabled for compatibility problem)

The fact is when I start the project, everything seems perfect but memory is increasing for every scenes (page) I made. Page1: 30Mb., Page2: 40, Page 3: 54, Page 4: 65... After 7 or 8 scenes, Instruments, Xcode or the iPad itself hangs the application without any message (except Instruments with a final Low memory Warning).

Why there's no memory releasing after each scenes? Maybe it's because ARC and the no super dealloc variable. Why textures appears unload perfectly but seems like there's no unload because memory is growing without control until crash?

like image 307
Julio César Fernández Muñoz Avatar asked Feb 11 '12 02:02

Julio César Fernández Muñoz


2 Answers

I was having a similar problem with memory retention and no leaks showing up in instruments. I couldn't get -(void) dealloc to even get called until I wrote the following into every scene's .m file:

-(void) onExit {
    //unschedule selectors to get dealloc to fire off
    [self unscheduleAllSelectors];
    //remove all textures to free up additional memory. Textures get retained even if the sprite gets released and it doesn't show as a leak. This was my big memory saver
    [[CCTextureCache sharedTextureCache] removeAllTextures];
    [super onExit];
}

After implementing this, my memory was released after every replaceScene: was called. Hope this is of some use to you.

like image 86
BobbyScon Avatar answered Nov 18 '22 16:11

BobbyScon


After months of working, I learned the most important lesson on Cocos2D. The retain increase by one when you put any CCNode object on a CCArray or NSArray or NSDictionary... This means you must release the objects from this objects before the CCLayer or CCScene dealloc.

You must put a [array removeAllObjects] or [dictionary release] on the - (void) cleanup and after all your objects has removed, then put a [super cleanup];

In the meantime, on - (void) onExit you must remove all scheduler from the instance. Not only a scheduler itself. Remember to stopAllActions on any CCNode. But, carefully, because stoping actions from CCNodes (Sprites or something) must be on cleanup, before any removeAllObjects.

And remember: if CCLayer or CCScene does not remove properly, SimpleAudioEngine not will release the audio too.

like image 3
Julio César Fernández Muñoz Avatar answered Nov 18 '22 17:11

Julio César Fernández Muñoz