这是我的代码简化:
NSMutableArray* buildBlocks = [[[NSMutableArray alloc] initWithCapacity:0] retain];
Block* selectedBlock = [[[Block alloc] init] retain];
// Add several blocks to "buildBlocks"
for( int i=0; i < [buildBlocks count]; i++)
{
Block* tempBlock = [buildBlocks objectAtIndex:i];
if( tempBlock.selected )
{
// Move the block to the selected block
selectedBlock = tempBlock;
// Take the block out of the array
[buildBlocks removeObjectAtIndex:i];
}
}
// Some code later
if( selectedBlock.selected ) // <---- Crashes here
{
// Do stuff
}
我想将所选块复制到“SelectedBlock”,从块中删除块,然后再使用“SelectedBlock”。当我使用这段代码时,我总是得到“EXC_BAD_ACCESS。我觉得程序在我想要之前发布了”SelectedBlock“中的数据。我做错了什么?
更新
感谢大家的帮助。我修好了。
答案 0 :(得分:5)
Block* selectedBlock = [[[Block alloc] init] retain];
这会创建(并且不必要地保留,因为您已经拥有它)一个新的Block。当你的目标是找回你已经拥有的那个时,你为什么要创建一个新的?
// Move the block to the selected block selectedBlock = tempBlock;
这个评论没有意义。什么都没有从一个块移动到另一个块;您将selectedBlock
变量设置为指向从数组中获取的块。在此之后,selectedBlock
和tempBlock
都指向同一个块,即数组中的块。
// Take the block out of the array [buildBlocks removeObjectAtIndex:i];
该数组拥有它包含的所有块,因此当您从阵列中删除块时,阵列会释放它。如果那是该块的唯一所有权,那么该块将被解除分配。此后对它的任何使用都是无效的。
比如......
if( selectedBlock.selected ) // <---- Crashes here
selectedBlock
指向然后从阵列中删除的块。假设数组是拥有它的唯一东西,到目前为止它是一个死对象,所以是的,发送消息会导致崩溃。
您保留了初始化selectedBlock
的对象,但未保留您稍后替换该对象的对象。保留该初始对象不会主动保留您分配给该变量的任何未来对象;它只保留了那个初始对象。
您需要更改几件事:
将selectedBlock
初始化为nil
,而不是指向新版块的指针。
不要随意保留东西。始终保持目的。如果你不完全理解为什么保留某些东西是正确的要做的事情(“使它不崩溃”本身不是一个可接受的理由),不要只是保留它。了解the Advanced Memory Management Programming Guide中的内存管理规则,您就会知道何时需要保留,以及为什么retain
[[[Block alloc] init] retain]
中的release
是不必要的。
当您保留某些内容时,请始终使用autorelease
或selectedBlock
消息进行平衡。保持不平衡是泄漏,泄漏最终会导致问题。在iOS下,从用户的角度来看,它们会导致崩溃(更准确地说,您使用了太多内存而系统会杀死您的应用)。
当您将数组中的对象分配给selectedBlock
时,保留它并在从阵列中删除它之前自动释放它。保留使您成为所有者,自动释放使其成为临时的;作为拥有者,只要持续时间,将使对象保持足够长的时间以便您使用它,防止崩溃。
不要问所选的块是否已被选中。如果选择了selectedBlock
,则只指定一个块的指针,因此当您使用selectedBlock
时,您已经知道它已被选中。结合上面的#1,您只需测试nil
是nil
;如果它不是nil
,则会有一个选定的块,如果它是{{1}},则表示您没有找到(即没有)所选的块。
使用此代码后,将其转换为ARC。 (编辑/重构菜单中有一个菜单项。)然后您不必保留或释放或自动释放任何内容;大多数事情都有效。
答案 1 :(得分:0)
我想说当你从数组中删除它时,你正在释放该块,但你已经在那里放入了虚假(和不必要的)retains
所以很难说出发生了什么没有看到你遗漏的代码。
通常情况下,当我从数组中移除对象并想要保持它时,我保留它。但是你总是过度保留,以至于可能不是问题,但是如果没有看到方法的其余部分,我就无法确定。
答案 2 :(得分:0)
你走了:
NSMutableArray* buildBlocks = [[[NSMutableArray alloc] initWithCapacity:0] retain];
Block* selectedBlock;
// Add several blocks to "buildBlocks"
for( int i=0; i < [buildBlocks count]; i++)
{
Block* tempBlock = [buildBlocks objectAtIndex:i];
if( tempBlock.selected )
{
// Move the block to the selected block
selectedBlock = tempBlock;
[selectedBlock retain]; // Retain selectedBlock here
// Take the block out of the array
[buildBlocks removeObjectAtIndex:i];
}
}
// Some code later
if( selectedBlock.selected ) // <---- Crashes here
{
// Do stuff
}
[selectedBlock release]; // release when done.
基本上,你在第2行保留了一个全新的,从未使用过的Block.selectedBlock从未得到保留,当你从阵列中删除它时,它被销毁了。因此,selectedBlock指向一个旧陈旧的被破坏的内存导致崩溃。