2012-02-11 18 views
5

Tengo un gran problema y no entiendo muy bien por qué ocurre. Este es el caso:El proyecto Cocos2D con muchas escenas no libera memoria correctamente

  • Tienen un gran proyecto en Cocos2D con 10 escenas. Cada escena es una página de un libro con grandes sprites. Utiliza la implementación de Kobold2D 1.0.2.
  • Cada página tiene objetos comunes en una clase singleton, para poner menús comunes a través de LayerColor.
  • Los sprites son TexturePacker en PVR.CCZ RGBA4444 y en la memoria del iPad tienen alrededor de 16-20Mb por cada hoja de sprites cargada.
  • Uso CCTransitionTurnPage para replaceScene para una a la siguiente.
  • En el método init de cada página (clase), cargue la textura y el archivo de estructura.
  • En el método onExit de cada página (clase), descargue las texturas y frameFile. Usé el dumpCachedTextureInfo y me dice que las texturas se cargan y descargan de la memoria a la perfección.
  • Por supuesto, remuevo del niño todos los objetos. Todos mis sprites son variables comunes declaradas en la sección de interfaz en .h, porque necesito acceder a ellas en cada método de la clase.
  • Mi proyecto se realiza con la integración Kobold2D en un proyecto ARC (pero usted sabe el proyecto Kobold2D adjunto ha ARC no está habilitado para el problema de la compatibilidad)

El hecho es que cuando comienzo del proyecto, todo parece perfecto, pero la memoria está aumentando para cada escena (página) que hice. Página1: 30Mb., Página2: 40, Página 3: 54, Página 4: 65 ... Después de 7 u 8 escenas, Instruments, Xcode o el iPad cuelgan la aplicación sin ningún mensaje (excepto los instrumentos con una advertencia de memoria baja final) .

¿Por qué no hay memoria liberando después de cada escena? Tal vez sea porque ARC y la variable no super dealloc. ¿Por qué las texturas parecen descargarse perfectamente pero parece que no hay descarga porque la memoria crece sin control hasta que se cuelga?

+0

Establezca un punto de interrupción en el método dealloc de una escena, si no se llama dealloc, tiene un ciclo de retención (ARC no puede evitar eso, consulte también: http://stackoverflow.com/questions/3634435/can-any -one-explain-retain-cycle-with-example-codeobjective-c-and-how-can-we). En particular, compruebe que ninguna de las propiedades de CCNode * tenga atributos fuertes o débiles, debe establecerse para asignar. – LearnCocos2D

+2

Finalmente debo deshabilitar ARC, debido a este ciclo de retención en la escena. No puedo encontrar ninguna solución para hacer un trámite real de cada escena y debo deshabilitar ARC. Cuando lo hago, todo va bien. RemoveAllTextures ahora congela la memoria (con ARC no) y super dealloc funcionan perfectamente. Cuando tuve habilitado ARC, anulé dealloc no fire, y usé onExit para descargar texturas y congelar memoria, pero no funciona. ¡Muchas gracias por tu ayuda! –

+2

Lo más probable es que la desactivación de ARC solo cambiara la forma en que se comportan los errores de código, en particular si tuvieras un ARC de referencia circular o ningún ARC debería hacer la diferencia. Es posible que ahora esté filtrando objetos en silencio. – LearnCocos2D

Respuesta

10

Estaba teniendo un problema similar con la retención de memoria y no aparecen fugas en los instrumentos. No pude conseguir - (void) dealloc para conseguir incluso llama hasta que escribí lo siguiente en un archivo .m de cada escena:

-(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]; 
} 

Después de implementar esto, mi memoria fue puesto en libertad después de cada replaceScene: se llamaba. Espero que esto sea de alguna utilidad para ti.

+2

Siempre utilicé [[CCTextureCache sharedTextureCache] removeUnusedTextures]; pensando que Cocos2D se daría cuenta de que la textura no se usa y, por lo tanto, la eliminará. Resulta que no puede determinarlo de manera confiable, por lo tanto, eliminar todas las texturas, aunque sea más lento, es mejor para evitar problemas de memoria. – axello

3

Después de meses de trabajo, aprendí la lección más importante sobre Cocos2D. El retener se incrementa en uno cuando coloca un objeto CCNode en un CCArray o NSArray o NSDictionary ... Esto significa que debe liberar los objetos de estos objetos antes de que el CCLayer o CCScene dealloc.

Debe poner un [conjunto removeAllObjects] o [versión de diccionario] en la limpieza - (nulo) y después de que todos sus objetos se hayan eliminado, a continuación, coloque una [super limpieza];

Mientras tanto, en - (nulo) onExit debe eliminar todo el planificador de la instancia. No solo un programador en sí mismo. Recuerde detener AllActions en cualquier CCNode. Pero, con cuidado, porque las acciones de detención de CCNodes (Sprites o algo así) deben estar en la limpieza, antes de cualquier removeAllObjects.

Y recuerde: si CCLayer o CCScene no se eliminan correctamente, SimpleAudioEngine no liberará el audio también.

+0

Esta fórmula es para proyectos ARC o no ARC. :) –

Cuestiones relacionadas