2012-02-11 5 views
5

Ho un grosso problema e non capisco molto bene perché si verifica. Questo è il caso:Il progetto Cocos2D con molte scene non rilascia correttamente la memoria

  • Avere un grande progetto in Cocos2D con 10 scene. Ogni scena è una pagina di un libro con enormi folletti. Utilizza l'implementazione di Kobold2D 1.0.2.
  • Ogni pagina contiene oggetti comuni in una classe singleton, per mettere un menu comune tramite LayerColor.
  • Gli sprite sono TexturePacker in PVR.CCZ RGBA4444 e nella memoria iPad sono circa 16-20 Mb ogni spites caricato.
  • Uso CCTransitionTurnPage per replaceScene per uno a quello successivo.
  • Al metodo init di ciascuna pagina (classe), caricare la trama e FrameFile.
  • Al metodo onExit di ogni pagina (classe), scaricare le trame e il file di frame. Ho usato il dumpCachedTextureInfo e mi ha detto che le trame vengono caricate e scaricate perfettamente dalla memoria.
  • Ovviamente rimuovo dal bambino tutti gli oggetti. Tutti i miei sprite sono variabili comuni dichiarate nella sezione dell'interfaccia in .h, perché ho bisogno di accedervi in ​​ogni metodo della classe.
  • Il mio progetto è realizzato con l'integrazione Kobold2D in un progetto ARC (ma si sa il progetto Kobold2D allegato è ARC non abilitato per problemi di compatibilità)

Il fatto è che quando avvio il progetto, tutto sembra perfetto, ma la memoria sta aumentando per ogni scena (pagina) che ho creato. Pagina1: 30 Mb., Pagina 2: 40, Pagina 3: 54, Pagina 4: 65 ... Dopo 7 o 8 scene, Strumenti, Xcode o l'iPad stesso blocca l'applicazione senza alcun messaggio (eccetto Strumenti con un Avviso di memoria insufficiente finale) .

Perché non viene rilasciata memoria dopo ogni scena? Forse è perché ARC e la variabile no super dealloc. Perché le trame sembrano scaricare perfettamente ma sembra che non ci sia lo scaricamento perché la memoria cresce senza controllo fino allo schianto?

+0

Impostare un punto di interruzione nel metodo dealloc di una scena, se non si chiama dealloc si ha un ciclo di conservazione (ARC non può impedirlo, consultare anche: http://stackoverflow.com/questions/3634435/can-any -one-spiega-mantenere-ciclo-con-esempio-codeobjective-c-e-how-can-noi). In particolare, verifica che nessuna delle proprietà CCNode * abbia attributi forti o deboli, dovrebbero essere impostati per l'assegnazione. – LearnCocos2D

+2

Infine devo disattivare ARC, a causa di questo ciclo di conservazione sulla scena. Non riesco a trovare alcuna soluzione per fare un vero dealloc di ogni scena e devo disabilitare ARC. Quando lo faccio, tutto va bene. RemoveAllTextures ora congela la memoria (con ARC no) e super dealloc funziona perfettamente. Quando ho abilitato l'override di ARC, non ho attivato dealloc, e ho usato onExit per scaricare trame e bloccare la memoria, ma non funziona. Grazie mille per il vostro aiuto! –

+2

Molto probabilmente la disattivazione di ARC ha cambiato il modo in cui si comportano i bug del codice, in particolare se si dispone di un ARC di riferimento circolare o di ARC non dovrebbe fare alcuna differenza. È possibile che tu stia perdendo oggetti in silenzio. – LearnCocos2D

risposta

10

Stavo riscontrando un problema simile con la conservazione della memoria e assenza di perdite negli strumenti. Non ho potuto ottenere - (void) dealloc perfino di chiamata fino a quando ho scritto quanto segue nel file di .m di ogni scena:

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

Dopo l'implementazione di questo, la mia memoria è stato rilasciato dopo ogni replaceScene: è stato chiamato. Spero che questo ti sia di qualche utilità.

+2

Ho sempre usato [[CCTextureCache sharedTextureCache] removeUnusedTextures]; pensando che Cocos2D possa capire che la trama è effettivamente inutilizzata e quindi rimuoverla. Risulta che non può determinarlo in modo affidabile, quindi removeAllTextures, anche se più lento, è meglio prevenire i problemi di memoria. – axello

3

Dopo mesi di lavoro, ho imparato la lezione più importante su Cocos2D. Il mantenimento aumenta di uno quando si inserisce un oggetto CCNode su un CCArray o NSArray o NSDictionary ... Ciò significa che è necessario rilasciare gli oggetti da questi oggetti prima del dealloc CCLayer o CCScene.

È necessario inserire un [array removeAllObjects] o [dictionary release] sul - (void) cleanup e dopo che tutti gli oggetti sono stati rimossi, quindi inserire un [super cleanup];

Nel frattempo, su - (void) onExit è necessario rimuovere tutto lo scheduler dall'istanza. Non solo uno schedulatore in sé. Ricordarsi di arrestareAllAzioni su qualsiasi CCNode. Ma, attentamente, perché l'arresto delle azioni da CCNodes (Sprites o qualcosa) deve essere in corso di pulizia, prima di qualsiasi removeAllObjects.

E ricorda: se CCLayer o CCScene non si rimuovono correttamente, SimpleAudioEngine non rilascia anche l'audio.

+0

Questa formula è per progetti ARC o non ARC. :) –