0

initで割り当て、deallocでリリースしたメッセージというNSMutableArrayがあります。通常、CCCallFuncNDアクションで文字列を問題なく使用できます。これは、次のような配列のインデックスであっても問題ありません。

displayMessagePiece = [CCCallFuncND actionWithTarget:self selector:@selector(displayMessageBoxString : data:) data:[[NSString stringWithFormat:[labelPieces objectAtIndex:i]] retain]];

ただし、可変文字列を使用すると、コードが含まれているコード行を指す緑色の矢印が表示され、16進数で「EXC_BAD_ACCESS」と表示されてクラッシュします。

NSMutableStringを使用しようとしているアクションとシーケンスは次のとおりです。

id displayMessage = [CCCallFuncND actionWithTarget:self selector:@selector(displayMessageBoxString : data:) data:[[NSString stringWithFormat:[message copy]] retain]];

[self runAction:[CCSequence actions:displayMessage,nil]];

メッセージだけも試しましたが、[メッセージコピー]を使用していることに注意してください。

4

1 に答える 1

3

私は悪い習慣のにおいがします:

NSString* s = [[NSString stringWithFormat:[labelPieces objectAtIndex:i]] retain];
[CCCallFuncND actionWithTarget:self 
                      selector:@selector(displayMessageBoxString:data:)
                          data:s];

まず第一に、あなたはあなたが解放するかもしれないし、しないかもしれない文字列を保持しています。displayMessageBoxStringセレクターが呼び出される保証はありません。たとえば、call funcアクションを実行しているノードは、セレクターが呼び出される前にシーンから削除されたり、セレクターが呼び出される前にシーン全体を変更したりする場合があります。どちらの場合も、文字列が漏れることになります。

CCCallFuncOがある場合にCCCallFuncNDを使用する理由もありません。CCCallFuncNDは、プロジェクトでARCを使用している場合に特に有害です。その場合、オブジェクトをvoid *にブリッジキャストする必要があります。その時点で、ARCはメモリを解放するだけで、ARC以外のコードがオブジェクトのメモリを管理していると想定します。同じことが実際には自動リリースにも当てはまるかもしれませんが、私はそれについて100%確信していません。

したがって、最初の仕事はCCCallFuncOを使用して、問題がなくなったかどうかを再テストすることです。また、自動解放に依存します。すべての場合に解放できるわけではないため、文字列を保持しないでください。

NSString* s = [NSString stringWithFormat:[labelPieces objectAtIndex:i]];
[CCCallFuncO actionWithTarget:self 
                     selector:@selector(displayMessageBoxString:)
                       object:s];

これで、最小ターゲットがiOS 4.0の場合、代わりに実際にブロックを使用する必要があります。これは、送信者とオブジェクトの両方が同時に必要な場合に特に当てはまります。ブロックはローカルスコープにアクセスできるため、この場合は最も単純なCCCallBlockアクションを使用できます。

NSString* s = [NSString stringWithFormat:[labelPieces objectAtIndex:i]];
[CCCallBlock actionWithBlock:^void(){
    CCLOG(@"sender is: %@, string is: %@", self, s);
}];

その他、すべての問題が解決され、メモリリークが発生しないことが保証されています。

次のように、void()なしでブロックを書き込むこともできることに注意してください。

[CCCallBlock actionWithBlock:^{
    CCLOG(@"sender is: %@, string is: %@", self, s);
}];

個人的には、戻り値のタイプとパラメーターがない場合でも、自分自身と他の人に思い出させることが役立つと思います。

于 2012-04-06T20:40:25.737 に答える