我有一个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]];
注意我使用[留言复制],虽然我也尝试过留言。
答案 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);
}];
就个人而言,我觉得有必要提醒自己和其他人关于返回类型和参数,即使没有。