Objective c 内存泄漏-可能是由于块超出范围

Objective c 内存泄漏-可能是由于块超出范围,objective-c,objective-c-blocks,Objective C,Objective C Blocks,我有一个涉及块的内存泄漏,我认为它与这个剥离的代码段有关。我认为问题在于,在我将tapCbk传递给scrollLayerItem之前,块定义超出了范围 我想我可以在每个定义中复制块,并在最后释放它,但这似乎很容易出错。我宁愿保留开关,因为我在这些箱子里做更多的事情。我使用MRC 有没有更好的办法解决这个问题 void (^tapCbk)(void) = nil; switch (state) { case INVITED: tapCbk = ^{ :

我有一个涉及块的内存泄漏,我认为它与这个剥离的代码段有关。我认为问题在于,在我将tapCbk传递给scrollLayerItem之前,块定义超出了范围

我想我可以在每个定义中复制块,并在最后释放它,但这似乎很容易出错。我宁愿保留开关,因为我在这些箱子里做更多的事情。我使用MRC


有没有更好的办法解决这个问题

void (^tapCbk)(void) = nil;

switch (state)
{
  case INVITED:
    tapCbk =
    ^{
       :
    };
    break;

  case SOMETHING_OTHER:
    tapCbk =
    ^{
       :
    };
    break; 

  : // Lots of more cases, and a default
}

ScrollLayerItem *item = [ScrollLayerItem itemWithNode:scrollLayerItemNode
                                               tapCbk:tapCbk];

在将块传递到创建块的函数之外之前,必须创建块的副本并自动释放它:

tapCbk = [[tapCbk copy] autorelease];

或者,只需使用ARC。

由块文字创建的块仅在块文字的局部范围内有效。在本例中,这些块文字的局部范围是switch语句的主体。将块存储在switch语句体之后使用的变量中,因此需要在块离开switch语句体之前复制它


如果没有开关,而是在顶层创建了块,例如void^tapCbkvoid=^{…};,那你就不必复制了。如果在这种情况下仍然存在问题,那么您的+[ScrollLayerItemWithNode:tapCbk:tapCbk]方法就有问题。

有更好的方法解决这个问题吗?是的:使用弧。当然!这样就不那么容易出错,因为复制和自动释放在同一个位置。很好@Free昵称否,因为与其他对象不同,块是堆栈变量。它们必须被复制。请参见,并且在将块传递到创建它的函数之外之前,您必须创建块的副本并自动释放它:不正确,这里也不适用。在将块传递给块类型的参数之前,不必复制该块。使用tapCbk:命名方法表示此参数为块类型。在内存管理约定下,接受块类型参数的函数将负责复制它,如果它需要存储它。或者,只需使用ARC。如果将块传递给非块类型的参数,ARC不保证复制块。那样的话,你还是应该复制它。