Jus*_*ios 0 iphone cocoa-touch objective-c
这是我的代码简化:
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
}
Run Code Online (Sandbox Code Playgroud)
我想将所选块复制到"SelectedBlock",从块中删除块,然后再使用"SelectedBlock".当我使用这段代码时,我总是得到"EXC_BAD_ACCESS.我觉得程序在我想要它之前发布了"SelectedBlock"中的数据.我做错了什么?
更新:
感谢大家的帮助.我修好了它.
Run Code Online (Sandbox Code Playgroud)Block* selectedBlock = [[[Block alloc] init] retain];
这会创建(并且不必要地保留,因为您已经拥有它)一个新的块.当你的目标是找回你已经拥有的那个时,你为什么要创建一个新的呢?
Run Code Online (Sandbox Code Playgroud)// Move the block to the selected block selectedBlock = tempBlock;
这个评论没有意义.什么都没有从一个块移动到另一个块; 您将selectedBlock变量设置为指向从数组中获取的块.后这一点上,selectedBlock和tempBlock都指向相同的块,这是阵列中的块.
Run Code Online (Sandbox Code Playgroud)// Take the block out of the array [buildBlocks removeObjectAtIndex:i];
该阵列拥有它包含的所有块,因此当您从阵列中删除块时,阵列会释放它.如果那是该块的唯一所有权,那么该块将被解除分配.此后对它的任何使用都是无效的.
如…
Run Code Online (Sandbox Code Playgroud)if( selectedBlock.selected ) // <---- Crashes here
selectedBlock指向您获得的块然后从阵列中删除.假设数组是拥有它的唯一东西,那么此时它就是一个死对象,所以是的,向它发送消息会导致崩溃.
您保留了初始化的对象selectedBlock,但不保留稍后替换该对象的对象.保留该初始对象不会主动保留您分配给该变量的任何未来对象; 它只保留了那个初始对象.
您需要更改几件事:
初始化selectedBlock为nil,而不是指向新块的指针.
不要随意保留东西.始终保持目的.如果你不完全理解为什么保留某些东西是正确的事情("使它不崩溃"本身不是一个可接受的理由),不要只是保留它.了解内存管理规则的高级内存管理编程指南,当你需要保留你就会知道,为什么你retain在[[[Block alloc] init] retain]是不必要的.
保留某些内容时,请始终使用release或autorelease消息进行平衡.保持不平衡是泄漏,泄漏最终会导致问题.在iOS下,从用户的角度来看,它们会导致崩溃(更确切地说,您使用了太多内存而系统会杀死您的应用程序).
当您从数组中分配对象时selectedBlock,保留它并在从阵列中删除它之前自动释放它.保留使您成为所有者,自动释放使其成为临时的; 作为拥有者,只要持续时间,将使对象保持足够长的时间以便您使用它,防止崩溃.
不要问所选的块是否被选中.您只需指定一个Block指针,selectedBlock如果它已被选中,那么当您使用时selectedBlock,您已经知道它已被选中.以上#1相结合,你可以简单地测试是否selectedBlock是nil; 如果不是nil,则有一个选定的块,如果是nil,则表示您没有找到(即没有)所选的块.
使此代码工作后,将其转换为ARC.(编辑/重构菜单中有一个菜单项.)然后您不必保留或释放或自动释放任何内容; 大多数事情都有效.
| 归档时间: |
|
| 查看次数: |
67 次 |
| 最近记录: |