2

私はCocos2dのプロジェクトでここで苦しんでいます。私は自分の「誤解」の核心を切り離す小さなプロジェクトを作成しました。

以下は、2つの別々のシーンを作成し、最初の子を再利用するふりをする非常に単純なコードです。ARCを使用するプロジェクトでcocos2dv2を使用しています。

CCLabelTTF *label = [CCLabelTTF labelWithString:@"Hello ARC World" fontName:@"Marker Felt" fontSize:64];

CCScene *scene1 =  [HelloWorldLayer scene];
CCScene *scene2 =  [HelloWorldLayer2 scene];

[director_ pushScene: scene1];

// I add my label to the main layer of my scene1.
[[scene1 getChildByTag:1] addChild:label];
//I reset my own scene1 pointer to make sure only the director points to it.
//scene1 = nil;
// I replace the scene, and hope that the old scene1 will be killed by cocos
[director_ replaceScene: scene2];
// When I want to reuse my "label" object, I get the "child already added..." exception
[[scene2 getChildByTag:2] addChild:label];

なぜこれが間違っているのですか?replaceSceneが私のためにすべての仕事をすることになっているので、RemoveAllChildrenなどをいじってはいけないことを読みました。ここで何か根本的に間違っていると思いますか?異なるシーン間でのオブジェクトの再利用は固く禁じられていますか?

4

3 に答える 3

4

他の人がすでに指摘しているように、ノードは1つの親しか持つことができません。実際の誤解を指摘させてください。これがまたあなたのコードです:

CCScene *scene1 =  [HelloWorldLayer scene];
CCScene *scene2 =  [HelloWorldLayer2 scene];

2つのオブジェクトscene1とscene2を作成しました。現在のメソッドが終了するまで、スコープ内に残ります。これがあなたの問題の鍵です。

[director_ pushScene: scene1];
[[scene1 getChildByTag:1] addChild:label];

これで、scene1オブジェクトがcocos2dの観点からアクティブなシーンになりました。子としてラベルオブジェクトを追加しました。

[director_ replaceScene: scene2];

scene2オブジェクトはcocos2dのアクティブなシーンではありません。ただし、scene1オブジェクトはまだスコープ(現在のメソッドのローカルスコープ)にあるため、現在のコードブロックが終了するまで(つまり、メソッドが戻るまで)、割り当てが解除されません。

[[scene2 getChildByTag:2] addChild:label];

ここでは、すでにシーン1の子ノードであるシーン2に子ノードとしてラベルを追加しようとしています。BAMM!そして、正当な理由があります。

ARCを使用していると仮定すると、次のことを試してみてください。

{
    CCScene *scene1 =  [HelloWorldLayer scene];
    [director_ pushScene: scene1];
    [[scene1 getChildByTag:1] addChild:label];
}
{
    CCScene *scene2 =  [HelloWorldLayer2 scene];
    [director_ replaceScene: scene2];
    [[scene2 getChildByTag:2] addChild:label];
}

コードブロックを追加することにより、replaceSceneを実行するときにscene1オブジェクトの割り当てが解除されます。なんで?シーン1は最初のコードブロックのスコープ内にあるだけなので、2番目のコードブロックでは、シーン1変数はすでにスコープ外にあり、ARCは、cocos2dがreplaceSceneメソッド中にシーン1へのすべての強力な参照も削除すると仮定して、メモリから解放できることを認識しています。

この最後の仮定は、cocos2d自体がARCを使用していないため、私にはわかりません。したがって、cocos2dの自動リリースの動作方法により、replaceSceneの後もscene1オブジェクトが存続する可能性があります。遅くとも、scene1オブジェクトは、次のフレームが始まる前に解放されます。

于 2013-01-16T22:35:25.527 に答える
2

cocosオブジェクトは1つの親しか持つことができません。シーン2に追加しようとすると、「label」オブジェクトにはすでに親(タグ1を持つシーン1の子)があります。意図している場合は、scene2のラベルオブジェクトの別のインスタンスを作成する必要があります。

于 2013-01-16T20:02:30.163 に答える
0

ここで実際に起こっていることscene1は、ARCによってまだ保持されているため、割り当てが解除されていないことです。

子供の両親はまだメソッドnilの中にいます。CCNode deallocシーンの割り当てが解除されない場合でも、子の親はシーン1であり、これは幸いにも存在します。

行ってシーン2にラベルを追加すると、そのアサーションにつまずきますchild.parent == nil

これはcocos2dまたはARCの誤りではありません。これを引き起こすのは、コードを記述した方法です。一般に、このようなCCNodeを再利用することはお勧めできません。

于 2013-01-16T21:34:03.640 に答える