为什么我的Objective-C对象被解除分配?

Tom*_*und 8 memory iphone objective-c

我有一个神秘地解除分配的Objective-C对象(在iOS游戏应用程序中)的问题.

该对象是一个GameCharacter实例,它实例化如下:

for (int c = 0; c < kNrOfGuards; c++) {
    GameCharacter* guard = [[GameCharacter alloc] initGuard:self sprite:guardSprite];
    [characterArray addObject:guard];
    [guard release];
}
Run Code Online (Sandbox Code Playgroud)

我还有一个方便的方法来查找GameCharacter:

- (GameCharacter*)findCharacterWithIndex:(int)index {
    return [characterArray objectAtIndex:index];
}
Run Code Online (Sandbox Code Playgroud)

生成错误的代码如下所示:

for (int c = 0; c < [self characterCount]; c++) {
    GameCharacter* tempCharacter = [self findCharacterWithIndex:c];
    if (tempCharacter.playerId == playerIndex]) {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

运行此代码一段时间(从不立即)会在控制台中生成错误:

[GameCharacter playerId]:发送到解除分配的实例0x4e47560的消息

使用NSZombieEnabled技巧,我设法找到导致问题的对象,但我仍然无法理解为什么要解除分配此对象.在我的代码中搜索"release"/"dealloc"不会产生任何线索.

我已经尝试删除"释放"(甚至添加"保留"!)到alloc/init循环(参见顶部),它似乎延长了应用程序可以运行的时间但不能完全解决问题.

任何提示将不胜感激!

编辑

感谢quixoto,Olie,Eiko,tc.,我发现它是我的GameCharacter对象正被释放,但我仍然不明白为什么.以下是反向时间顺序的跟踪日志:

#0 -[GameCharacter dealloc]
#1 objc_setProperty
#2 -[TiledGroundLayer setSelectedCharacter:]
#3 -[TiledGroundLayer selectNextCharacterForPlayer:searchStep:]
#4 -[GameScene selectNextCharacter:]
#5 -[GameScene endTurn]
#6 -[HUDLayer onClickDone:]
Run Code Online (Sandbox Code Playgroud)

这里发生的是,用户单击"完成",屏幕上的所选字符被更改,因此selectedCharacterTiledGroundLayer上的属性被更改(步骤#2-4).由于selectedCharacter拥有以前的GameCharacter对象,它似乎正在被释放.但为什么NSMutableArray([characterArray addObject:guard];)没有正确保留它?

Pau*_*der 2

根据您的更新:

#0 -[GameCharacter dealloc]
#1 objc_setProperty
#2 -[TiledGroundLayer setSelectedCharacter:]
Run Code Online (Sandbox Code Playgroud)

我猜想您正在释放对 setter 中对象的现有引用,然后保留新副本。但是,如果新对象恰好与现有引用完全相同,则您可能会将消息发送retain到已释放的对象。

-(void) setSelectedCharacter: (GameCharacter*) newCharacter
{
  [character release]; // Oops if character == newCharacter
  character = [newCharacter retain];
} 
Run Code Online (Sandbox Code Playgroud)