0

我正在使用 CCScene 的 GameScene 子类的一些静态实例。从 GameScene 调用

[[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];
4

3 回答 3

1

我闻到不好的做法。永远不要保留节点的静态实例。尤其是不在场景层次结构之外。它只是打破了 cocos2d 处理内存管理的方式。

如果您需要保留状态,请将此状态保存到单独的类中,但是当您更改场景时一定要让场景消失。然后在场景再次初始化时恢复状态。

您不能强制使用 dealloc 方法。想要这样做是代码异味的标志。但是,您可以覆盖该方法以在将节点作为子节点删除-(void) cleanup之前和之后运行反初始化代码。dealloc

编辑:什么时候在 dealloc 方法中添加这段代码是明智的?

[自我 removeAllChildrenWithCleanup:TRUE];

绝不。曾经。

Again, if you find you need to do this, there's a terrible bug somewhere. Cocos2D will have removed the child nodes by this time. In fact, it does so during the cleanup method, one way to cause cocos2d not to remove a node's children is when you override cleanup and not call [super cleanup].

Or perhaps when you keep it as a static instance, so it'll never actually call the cleanup method. And even worse would then continue to run scheduled updates and actions.

于 2012-09-12T21:00:19.083 回答
0

你的麻烦是你没有发布你的游戏场景。将其创建为

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

它将被正确释放。

无论如何,我认为没有必要将游戏场景创建为其他场景的孩子,但也许我对您的项目一无所知。

而且我无法理解,您在“静态CCScene”下是什么意思

于 2012-09-12T20:33:30.557 回答
0

Using 'Instruments' under Developer Tools, I was able to make some progress on this matter:

When the scene is created it should follow a few simple rules to keep the memory low:

  1. Allocate the sprites from smallest to largest
  2. Make sure to call [self unscheduleAllSelectors]; at the right times
  3. 如果您想在您的案例中看到显着的内存改进,请使用以下代码覆盖 -(void)dealloc 方法,因为每次加载 CCScene 时都会遇到这种情况:

    // Clean up memory allocations from sprites
    [[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
    [[CCDirector sharedDirector] purgeCachedData];
    [[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFrames];
    [CCSpriteFrameCache purgeSharedSpriteFrameCache];
    
于 2014-07-01T06:56:08.647 回答