Objective c 升级到SDK 5 for iOS后从NSMutableArray中删除对象会导致我的应用程序崩溃
[编辑]我重新安排了如何从列表中删除obj。这就是它最初仍然导致相同错误的原因 这就是问题中的代码。我相信我已经将错误缩小到从_blocksnsmutableArray中删除对象的那一行。在代码的其他部分中,我有完全相同的代码,从同一数组中删除类似的对象。由于某种原因,当调用此函数时,会导致游戏崩溃。在我升级到支持iOSSDK5和armv7的最新XCode之前,它没有这个问题。在升级XCode之前,它工作得很好。我走进一个项目,项目就会从屏幕上消失。现在,当我得到一件物品时,它就崩溃了。任何帮助都将不胜感激Objective c 升级到SDK 5 for iOS后从NSMutableArray中删除对象会导致我的应用程序崩溃,objective-c,ios,xcode,crash,sigabrt,Objective C,Ios,Xcode,Crash,Sigabrt,[编辑]我重新安排了如何从列表中删除obj。这就是它最初仍然导致相同错误的原因 这就是问题中的代码。我相信我已经将错误缩小到从_blocksnsmutableArray中删除对象的那一行。在代码的其他部分中,我有完全相同的代码,从同一数组中删除类似的对象。由于某种原因,当调用此函数时,会导致游戏崩溃。在我升级到支持iOSSDK5和armv7的最新XCode之前,它没有这个问题。在升级XCode之前,它工作得很好。我走进一个项目,项目就会从屏幕上消失。现在,当我得到一件物品时,它就崩溃了。任何帮助
-(void)itemCollision:(Collidable *)obj :(int)itemID :(int)objID: (bool)withPlayer{
[background removeChild:[obj getSprite] cleanup:YES];
[background removeChild:[obj getArrow] cleanup:YES];
[_blocks removeObject:obj];
//[obj release];
if(withPlayer){
if(itemID == 1){
[[SimpleAudioEngine sharedEngine] playEffect:@"Item2.mp3" pitch:1.0f pan:0.0f gain:0.3f];
points += (10 + level * 22);
}
}
}
错误消息是:“线程1:程序接收信号:“SIGARBRT”
下面是我调用itemCollision的代码:
-(bool) isCollision {
CCSprite *playerSprite = mob;//[mob getSprite];
CGRect playerRect = CGRectMake(playerSprite.position.x - (playerSprite.contentSize.width/2),
playerSprite.position.y - (playerSprite.contentSize.height/2),
playerSprite.contentSize.width,
playerSprite.contentSize.height);
//Player Collision
BOOL collision = FALSE;
for (Block *block in _blocks) {
CCSprite *blockSprite = [block getSprite];
CGRect blockRect = CGRectMake(blockSprite.position.x - (blockSprite.contentSize.width/2),
blockSprite.position.y - (blockSprite.contentSize.height/2),
blockSprite.contentSize.width,
blockSprite.contentSize.height + 1 + [mob getSpeed]);
if (CGRectIntersectsRect(blockRect, playerRect)) {
if ([block getItemID] != 0) {
[self itemCollision:block :[block getItemID] :[block getID] :TRUE];
continue;
}
if(playerSprite.position.y > blockSprite.position.y){
collision = TRUE;
}
if(collision) {
[[SimpleAudioEngine sharedEngine] playEffect:@"squish.caf"];
[self die];
return TRUE;
}
}
}
return FALSE;
}
下面是我如何从代码中其他地方的_块中删除对象。这是在重力计时器函数中:
NSMutableArray *blocksToDelete = [[NSMutableArray alloc] init];
for (Block *block in _blocks) {
CCSprite *blockSprite = [block getSprite];
//[block addSpeed:gravity];
[block setPreX:blockSprite.position.x];
[block setPreY:blockSprite.position.y];
blockSprite.position = ccp(blockSprite.position.x, blockSprite.position.y - [block getSpeed]);
if (blockSprite.position.y < -30 + blockSprite.contentSize.height / 2) {
[blocksToDelete addObject:block];
}
if(blockSprite.position.y - blockSprite.contentSize.height < [block getArrow].position.y){
[block getArrow].visible = FALSE;
}
}
for (Block *b in blocksToDelete) {
[_blocks removeObject:b];
[background removeChild:[b getSprite] cleanup:YES];
[background removeChild:[b getArrow] cleanup:YES];
[b release];
}
NSMutableArray*blocksToDelete=[[NSMutableArray alloc]init];
用于(块*块中的块){
CCSprite*blockSprite=[block getSprite];
//[块速度:重力];
[block setPreX:blockSprite.position.x];
[block setPreY:blockSprite.position.y];
blockSprite.position=ccp(blockSprite.position.x,blockSprite.position.y-[block getSpeed]);
if(blockSprite.position.y<-30+blockSprite.contentSize.height/2){
[blocksToDelete addObject:block];
}
if(blockSprite.position.y-blockSprite.contentSize.height<[block getArrow].position.y){
[block getArrow].visible=FALSE;
}
}
用于(块中的块*b删除){
[_块移除对象:b];
[background removeChild:[b getSprite]清理:是];
[background removeChild:[b getArrow]清理:是];
[b]释放;
}
我在这些项到达被此函数删除的点之前访问它们。同样,在我升级我的XCode之前,这些代码已经运行了几个月。如果数组在对象上有最后一次保留,则在您删除它时,它将被解除分配。您继续在方法的其余部分使用该对象,因此它需要保持活动状态。Certainl检查obj的retainCount以查看NSMUTABLEARRY是否具有最后一个retain是第一个开始的位置 如果我们目前假设情况就是这样,那么尝试以下替代方法:
-(void)itemCollision:(Collidable *)obj :(int)itemID :(int)objID: (bool)withPlayer
{
[[obj retain] autorelease];
[_blocks removeObject:obj];
[background removeChild:[obj getSprite] cleanup:YES];
[background removeChild:[obj getArrow] cleanup:YES];
if(withPlayer){
if(itemID == 1){
[[SimpleAudioEngine sharedEngine] playEffect:@"Item2.mp3" pitch:1.0f pan:0.0f gain:0.3f];
points += (10 + level * 22);
}
}
}
当调试器转到main.m时,通常是因为它在弹出自动释放池(一个没有调试符号的任务)时正在消亡,所以它转到最深的堆栈帧,它有源代码显示给您,在主线程上的自动释放池的情况下,它将是您的main()函数
您还应该尝试在Instruments中使用Zombies工具来运行此案例。这对跟踪此内容非常有帮助。很难确切知道在您共享的代码示例范围之外发生了什么,但一个粗略的猜测是您的“obj”被过度释放。当您从t中删除它时,它会被释放一次他创建了一个数组,然后您将再次释放它。考虑到传入该对象时该对象的保留计数,这可能是合适的,也可能是不合适的 要开始故障排除,请尝试使用Instrument Zombie工具-这将帮助您观察它是否确实被过度放大 您还可以对以下内容进行注释:
[obj release]
查看这是否停止了错误(这可能是解决方案,也可能不是解决方案,但在任何情况下都应该是有见地的)。是传入的对象(obj)是否在其他地方保留?当您从_blocks数组中删除它时,它的保留计数会减少1,我可能会冒昧地猜测它当时正在被释放。然后您再次调用它两次,然后再次释放,这肯定会表明您看到的错误类型。不要用“get”命名方法“前缀;只需将它们命名为
sprite
和arrow
。它仍然会崩溃,并以相同的错误转到main。实际上,我添加了[obj版本],因为我想我忘记了,那是在最初的崩溃之后。在代码删除obj精灵和obj箭头图形,然后将其从_块列表中删除之前,没有释放它。但同样的错误仍然发生。我将发布向该线程调用itemCollision的代码。请看一看。我仍然不太确定如何使用僵尸工具,或者如何使用它来帮助我解决这个问题。我会调查的。如果您能继续帮助我解决这个问题,我将不胜感激。“当然,首先要检查obj的retainCount,看看NSMutableArray是否有最后一个retain。”这根本不是一个开始。重新计算是没有用的。别管它了。最初我没有发布那个obj,这就是我添加它的原因。在我添加它之前,我仍然得到那个错误。我编辑了上面的代码,以显示它最初是怎样的。我如何确切地使用僵尸工具来查看它是否已发布?我还添加了更多的代码,可以帮助您了解我的代码的作用。
-(void)itemCollision:(Collidable *)obj :(int)itemID :(int)objID: (bool)withPlayer
{
[[obj retain] autorelease];
[_blocks removeObject:obj];
[background removeChild:[obj getSprite] cleanup:YES];
[background removeChild:[obj getArrow] cleanup:YES];
if(withPlayer){
if(itemID == 1){
[[SimpleAudioEngine sharedEngine] playEffect:@"Item2.mp3" pitch:1.0f pan:0.0f gain:0.3f];
points += (10 + level * 22);
}
}
}
[obj release]