Cocos2D removeChildByTag崩溃?

时间:2011-02-25 17:38:12

标签: iphone crash cocos2d-iphone removechild touch-event

问题摘要: 在我启动应用程序并按“新游戏”后,我使用CCDirector转换到GameScene。在那里,我添加了32个GamePiece对象,这些对象处理触摸事件,如下所示:

@interface GamePiece : NSObject <CCTargetedTouchDelegate>{  

    CCSprite* sprite;

    NSInteger row;
    NSInteger column;

}

//-(void)moveToRow:(NSInteger)newRow column:(NSInteger)newColumn;
-(id)initWithRow:(NSInteger)aRow column:(NSInteger)aColumn tag:(NSInteger)tag parent:(CCNode*)parent;
+(id)gamePieceWithRow:(NSInteger)aRow column:(NSInteger)aColumn tag:(NSInteger)tag parent:(CCNode*)parent;

@end

GamePiece.m:

...
- (BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
    CGPoint touchLocation = [GameScene locationFromTouch:touch];

    CCLOG(@"(%i, %i)", row, column); //<-----THIS!!!

    //Crash never makes it here....

    // Check if this touch is on the Spider's sprite.
    BOOL isTouchHandled = CGRectContainsPoint([sprite boundingBox], touchLocation);
    if (isTouchHandled){        
        id parent = sprite.parent;
        [parent gamePieceSelected:self inRow:row column:column];
    }

    return isTouchHandled;
}

...

- (void)dealloc {
    [[CCTouchDispatcher sharedDispatcher] removeDelegate:self]; //Important...
    [super dealloc];
}
@end

好的,所以在我加载32件之后,我使用以下方法加载更多碎片:

[parent gamePieceSelected:self inRow:row column:column];

如下:(GameScene.m)

-(void)gamePieceSelected:(GamePiece*)aGamePiece inRow:(NSInteger)row column:(NSInteger)column{
    [self removeChildByTag:18 cleanup:YES];
    //Array of index Path!!! row = row, section = column
    NSArray* moves = [self availableMovesForRow:row column:column];

    for(NSIndexPath* index in moves){ //Please forgive me for using NSIndexPath!! 
        [GamePiece gamePieceWithRow:[index row] column:[index section] tag:18 parent:self];
    }
}

基本上,当您点按GamePiece时,我会添加其他GamePiece个对象,其中包含tag = 18.然后我使用此标记删除“新”GamePiece个对象,然后添加其他.. ..

我的问题?

在录制GamePiece之后,“新”游戏片段会正确显示,但在我点击多次后它会崩溃!我的意思是,我点击GamePiece,新的游戏片出现了。然后,如果我点击另一个GamePiece,我会把手放在我的心脏上等待崩溃。有时它会崩溃,有时它不会崩溃......第三次,第四次,第五次......等等。在它崩溃之前我管理了10个水龙头的高分:P ......太随机了......

我的理论:

请参阅注释行//<------THIS,每次点击屏幕时,CCLOG都会被调用任意次,直到找到满足if语句的GamePiece,这有点儿正常,因为我同时加载了很多GamePiece个对象..

当它崩溃时(没有任何堆栈跟踪或消息),这个CCLOG会被调用几次,并且永远不会在if语句中进行!我认为这是因为它正在尝试向GamePiece已移除的removeChildWithTag:发送触摸消息。但我已经在dealloc中调用了[[CCTouchDispatcher sharedDispatcher] removeDelegate:self];,这导致了一个非常重要的事实:

如果我在点击GamePiece之前等待几秒钟,然后点击另一个,我有更大的机会不会崩溃!!

感觉我正在给它时间调用dealloc,并删除触摸代表......

修改 在我看来,在dealloc中添加CCLOG,它从未被调用过...... 结束编辑

我不确定这是否显而易见,但如果我不删除新添加的GamePieces,游戏永远不会崩溃......但我需要删除它们:P

请帮助,我已经和这个问题打了几天&gt;。

1 个答案:

答案 0 :(得分:2)

此!!:

[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:-1 swallowsTouches:YES]; //Important...

是最大的错误!

这段简洁的代码:

[[CCTouchDispatcher sharedDispatcher] removeDelegate:self];

实际上保留了委托......而且我从未达到dealloc,也从未从触摸调度员中删除Delegate并导致灾难......


修改

好的,有人想知道我最终删除了代表的位置!我很惊讶我没有提到它!

- (void)onExit {
    [[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
    // Never forget this!!
    [super onExit];
}