我对严肃的编程比较陌生,所以请原谅我的愚蠢,但我自己也没想到这一点。
我正在用cocos2d-iphone写一款游戏。我有一个场景对象在其ivars中有几个NSMutableSets - 单位,建筑物,火箭等。我在从这些NSMutableSets中删除对象时遇到问题。当一个子弹对象被初始化时,它会搜索一个它应该像这样损坏的目标:
...
for ( RXUnit * unit in targetSet ) {
if ( ccpDistance( unit.position, rayPoint ) < 20 ) {
...
[unit damageSelfBy:damage];
...
}
}
...
[unit damageSelfBy:damage]
方法如果没有足够的HP来维持伤害,则会杀死该单位。其中包括:
[scene.units removeObject:self];
(scene.units与上面循环中的targetSet是相同的NSMutableSet)
每当使用此行时,从该组中删除该单元时拍摄的子弹无法正确初始化。 bullet init方法执行到上面显示的for循环(是的,该单元确实被前一个子弹损坏并删除),但是在init方法中此循环之后的任何其他内容都没有被执行。
令人惊讶的是,应用程序继续正常运行,除了弹出的子弹外没有任何可见的效果。控制台不显示任何警告/错误,编译时也没有警告。
我还尝试通过在场景的更新方法中放置实际删除代码来延迟将单元从集合中移除的时间,但这没有帮助。
我想我可以制作一些丑陋的黑客来隐藏这个问题,但我相信它会在以后咬我的屁股。好吧,我真的很想了解发生了什么以及如何妥善解决它。
非常感谢任何帮助/想法。也许我甚至不应该在NSMutableSets中存储游戏对象?
答案 0 :(得分:3)
set容器是对象的唯一引用吗?如果在运行其方法时释放对象,我不确定是否存在已定义的行为。您可能需要将其标记为“死”,然后再执行清理步骤。
答案 1 :(得分:3)
如果从集合中删除对象,并且该集合是对象的唯一引用,则可以在此时释放该对象。想一想:正在运行的方法的对象现在可以消失。那是坏事。
这就是你的延迟移除工作的原因;这不是一招。你等到你使用完对象后才会等到然后你要删除它。但是,有一种比你的objectsToRemove
技巧更好的方法:
[self retain];
[self autorelease];
[scene.units removeObject:self];
autorelease
会在运行循环结束时将延迟的release
消息发送到您的对象,因此使用retain
,然后使用autorelease
,您可以阻止该对象从消失的第二个消失的scene.units
。