Cocos2D removeChildByTag 崩溃?

发布于 2024-10-19 01:07:34 字数 3009 浏览 3 评论 0原文

问题总结: 启动应用程序并按“新游戏”后,我使用 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 时,我会添加带有 tag = 18 的其他 GamePiece 对象。然后,我使用此标记删除“新”GamePiece 对象,并添加其他对象..

我的问题?

点击 GamePiece 后,“新”游戏块会正确显示,但在我点击多次后它会崩溃!我的意思是,我点击一个 GamePiece,新的 gamePieces 就会出现。然后,如果我点击另一个 GamePiece,我就会把手放在心上等待崩溃。有时会崩溃,有时不会……第三次、第四次、第五次……我在崩溃之前获得了 10 次点击的高分:P ...如此随机......

我的理论:

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

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

如果我在点击 GamePiece 后等待几秒钟然后再点击另一个游戏,我会有更高的不崩溃的机会!!

感觉就像我给它时间来调用 dealloc,并删除触摸委托...

编辑: 我想到在dealloc中添加一个CCLOG,但它从未被调用过...... 结束编辑

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

请帮忙,我有几天来一直在解决这个问题>。

Summary of the problem:
After I launch the app, and press "New Game", I use CCDirector to transition to the GameScene. There, I add 32 GamePiece objects, where these objects handle touch events as follows:

@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

Ok, so After I load 32 pieces, I load even more pieces using the method:

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

as follows: (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];
    }
}

So basically, when you tap a GamePiece, I add other GamePiece objects with tag = 18. I then use this tag to remove the "new" GamePiece objects, and add other ones..

My problem?

After taping a GamePiece, "new" game pieces appear appropriately, but it crashes after I tap more than once! I mean, I tap a GamePiece, the new gamePieces appears. Then, if I tap another GamePiece, I put my hand on my heart waiting for a crash.. Sometimes it crashes, other times it doesn't... The third time, fourth, fifth ... etc. I managed a highscore of 10 taps before it crashed :P ... so random....

My theory:

See the comment line //<------THIS, the CCLOG gets called an arbitrary number of times each time I tap the screen until it finds the GamePiece that satisfies the if statement, which is kinda normal, since I have many GamePiece objects loaded at the same time..

When it crashes (without any stack trace or messages), this CCLOG gets called a few times, and never makes it inside the if statement!! I think it is because it's trying to send a touch message to a GamePiece that has been removed by removeChildWithTag: .. But I already call [[CCTouchDispatcher sharedDispatcher] removeDelegate:self]; in dealloc, which leads to a very important fact:

If I wait a few seconds after taping a GamePiece before I tap another one, I have a higher chance of not crashing!!

It feels like I am giving it time to call dealloc, and remove the touch delegate...

EDIT:
It occurred to me to add a CCLOG in dealloc, and it was never called...
END EDIT

And am not sure if this is obvious, but if I DON'T remove the newly added GamePieces, the game never crashes... But I need to remove them :P

Please help, I have been fighting this issue for days >.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

—━☆沉默づ 2024-10-26 01:07:34

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

THIS!!:

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

was the biggest mistake EVER!!

This neat piece of code:

[[CCTouchDispatcher sharedDispatcher] removeDelegate:self];

actually retains the delegate... and I never reach dealloc, and never removeDelegate from the touch dispatcher and cause a catastrophe ...


EDIT:

Ok, someone wants to know where I ended up removing the delegate! And I am surprised that I didn't mention that!

- (void)onExit {
    [[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
    // Never forget this!!
    [super onExit];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文