0

状況:
CCCallFunc の直後に謎のクラッシュが発生します。つまり、ボタンがあります。ボタンには、後で識別するためのタグがあります。ボタンが押されると、いくつかのアクションを実行してアニメーションを実行し、アニメーションが完了すると、別のメソッドを CCCallFunc して別のシーンに遷移させます。CCCallFunc の直後にクラッシュします。以下ソースとエラー。

クラッシュのポイント (cocos2d ソース内):

// From CCActionInstant.m of cocos2d
-(void) execute
{
    /*** EXC_BAD_ACCESS on line 287 of CCActionInstant.m ***/
    [targetCallback_ performSelector:selector_];
}
@end

スレッド 1 のスナップショット:
スレッド 1 スタック

私のコード:
以下は、MenuLayer.m (ボタンを表示するための単純なメニュー) から取得したソースです。

// from MenuLayer.m
// …

@implementation MenuLayer

-(id) init{

    if((self=[super init])) {

    /****** Create The Play Button (As a CCMenu) ********/
        CCSprite *playSprite = [CCSprite spriteWithFile:@"playbutton.png"];

        CCMenuItemSprite *playItem = [CCMenuItemSprite itemFromNormalSprite:playSprite selectedSprite:nil target:self selector:@selector(animateButton:)];
        playItem.tag = 3001;
        playItem.position = ccp(160.0f, 240.0f);

        CCMenu *menu = [CCMenu menuWithItems:playItem, nil];
        menu.position = ccp(0.0f, 0.0f);
        [self addChild:menu z:0];

    }
}

// ...

- (void)animateButton:(id)sender{

    /*** Run an animation on the button and then call a function ***/
    id a1 = [CCScaleTo actionWithDuration:0.05 scale:1.25];
    id a2 = [CCScaleTo actionWithDuration:0.05 scale:1.0];
    id aDone = [CCCallFunc actionWithTarget:self selector:@selector(animationDone:)];
    [sender runAction:[CCSequence actions:a1,a2,aDone, nil]];

}
- (void)animationDone:(id)sender{

    /*** Identify button by tag ***/
    /*** Call appropriate method based on tag ***/
    if([(CCNode*)sender tag] == 3001){

    /*** crashes around here (see CCActionInstant.m) ***/
        [self goGame:sender];
    }
}

-(void)goGame:(id)sender{

        /*** Switch to another scene ***/
    CCScene *newScene = [CCScene node];
    [newScene addChild:[StageSelectLayer node]];

        if ([[CCDirector sharedDirector] runningScene]) {
            [[CCDirector sharedDirector] replaceScene:newScene]];
        }else {
            [[CCDirector sharedDirector] runWithScene:newScene];
        }
}
4

2 に答える 2

2

CCCallFun の代わりに CCCallFuncN を使用します。

CCCallFuncN はノードをパラメーターとして渡します。CCCallFun の問題は、ノードの参照が失われていることです。

CCCallFuncN でコードをテストしたところ、問題なく動作しました。

于 2012-05-22T19:22:12.823 に答える
2

ただの予感。メモリ リークをチェックする以外に、goGame メッセージを直接送信する代わりに、0 秒間隔でセレクターをスケジュールしてみてください。私は、ディレクターの replaceScene がシーンとそれに関連するすべてのオブジェクトのクリーンアップを引き起こすのではないかと疑っています。その結果、CCCallFunc アクションが未定義の状態になる可能性があります。通常は問題なく動作しますが、つまり、これは大ざっぱな、メモリ、またはオブジェクトのライフタイム管理に関する別の兆候にすぎません。

ところで、最低限 iOS 4 をサポートしている場合は、CCCallFunc の代わりに CCCallBlock を使用してください。その方が安全でクリーンです。

于 2012-05-21T21:19:09.053 に答える