2012-09-12 22 views
0

我正在使用CCScene的GameScene子類的一些靜態實例。從GameScene調用Cocos2d和iOS:如何處理靜態CCScene的dealloc方法

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

不會觸發GameScene的dealloc方法。

一旦我再次加載場景(並創建一個新的GameScene)的方法被稱爲:

+(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 

我想了解,如果有迫使dealloc方法的方式調用每次我替換(靜態)場景,而不僅僅是當內存被「釋放」時。

或者,如果我應該寫一些清理方法,以阻止正在進行的進程,我不想影響MainMenuScene(例如,我在GameScene的dealloc方法中放置了一個停止背景音樂方法調用,背景音樂處於靜態類中,並且不會作爲子對象添加到GameScene中,然後在MainMenuScene中繼續播放)。因此

我速戰速決的建議是做這樣的事情:

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

這是一個好辦法?

編輯:何時是明智的在dealloc方法中添加此代碼?

[self removeAllChildrenWithCleanup:TRUE]; 

回答

1

我聞到不好的做法。永遠不要保留一個節點的靜態實例。尤其不在場景層次之外。它只是打破了cocos2d處理內存管理的方式。

如果您需要保存狀態,請將此狀態保存到單獨的類中,但切換場景時請務必讓場景繼續。然後在場景再次進入時恢復狀態。

你不能強制dealloc方法。想要這樣做是代碼味道的一個標誌。但是,您可以覆蓋-(void) cleanup方法以在dealloc之前以及在將該節點作爲子節點刪除之後運行解除初始化代碼。

編輯:何時是明智的在dealloc方法中添加此代碼?

[self removeAllChildrenWithCleanup:TRUE];

從來沒有。永遠。

再一次,如果你發現你需要這樣做,那麼在某個地方有一個可怕的錯誤。到目前爲止,Cocos2D將刪除子節點。事實上,它在cleanup方法中這樣做,導致cocos2d不刪除節點的子節點的一種方式是當您重寫清理並且不調用[超清理]時。

或者,當你將它作爲一個靜態實例保存時,它實際上永遠不會調用清理方法。然後更糟的是會繼續運行預定的更新和操作。

+0

但很遺憾是一個痛苦。 LearnCocos2d中的GameScene類怎麼樣?我有一個MainMenu,我從中推送GameScene,然後從GameScene回到MainMenu。我將GameScene保持爲靜態,因爲它對於子節點很有用(例如,在您的代碼中,GameScene的子類通過其共享實例訪問該場景)。我相信我錯了。但是,請問您能否就ShootEmUp示例作出澄清?處理MainMenuScene和不同級別的最佳方法是什麼?有沒有Cocos2D內存管理的模式? – mm24

+0

在另一篇文章中爲LearnCocos2d發表了評論,謝謝:)! http://stackoverflow.com/questions/12396352/cocos2d-with-arc-what-is-the-best-implementation-of-singleton-pattern-for-games – mm24

0

你麻煩的是你不釋放你的遊戲場景。創建它爲

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

它將被釋放權利。

無論如何,我沒有看到任何需要創建遊戲場景作爲其他場景的孩子,但也許我不知道你的項目的一些東西。

而且我不明白,你是什麼意思下的「靜態CCScene」

+0

我使用ARC所以你的代碼時並不需要我猜(但我可能被錯誤地理解它)。我的遊戲場景是從主菜單分配的,並且從不是任何其他場景的孩子(但我不會在使用[self removeAllChildrenWithCleanup:TRUE]時忽略它)。對於靜態CCScene,我的意思是一個CCScene子類,它帶有一個靜態方法,它返回一個對在init方法中初始化的類對象的靜態實例的引用。 – mm24

0

使用「工具」下的開發工具,我能夠就這個問題取得了一些進展:

當場景創建,應該遵循一些簡單的規則來保持內存低:

  1. 分配從小精靈到最大
  2. 確保在合適的時間調用[self unscheduleAllSelectors];
  3. 覆蓋的 - (空)dealloc方法有,如果你想看到significan下面的代碼你的情況牛逼內存改進,因爲這將打擊每次CCScene加載時間:

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