Cocos2D:在CCCallFuncND操作中使用NSMutableString时的EXC_BAD_ACCESS

时间:2012-04-06 20:17:17

标签: nsstring cocos2d-iphone action sequence nsmutablestring

我有一个NSMutableArray调用消息,我在init中分配并在dealloc中释放。我通常可以在CCCallFuncND操作中使用字符串而不会出现问题,即使它是数组的索引,例如:

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

然而,如果我使用我的可变字符串,我会遇到一个崩溃的绿色箭头指向我所拥有的代码行,并且它说" 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]];

注意我使用[留言复制],虽然我也尝试过留言。

1 个答案:

答案 0 :(得分:3)

我闻到了不好的做法:

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

首先,你要保留一个你可能会或可能不会释放的字符串。无法保证调用displayMessageBoxString选择器。例如,可以在调用选择器之前从场景中删除运行调用func操作的节点,或者可以在调用选择器之前更改整个场景。在这两种情况下,你都会泄漏字符串。

当有CCCallFuncO时,也没有理由使用CCCallFuncND。当您的项目使用ARC时,CCCallFuncND特别有害。在这种情况下,你必须将对象桥接到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);
}];

Et瞧,所有问题都解决了,并保证不会造成任何内存泄漏。

请注意,您也可以像这样编写没有void()的块:

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

就个人而言,我觉得有必要提醒自己和其他人关于返回类型和参数,即使没有。