这会导致任何形式的保留周期吗?使用安全吗?

__block void (^myBlock)(int) = [^void (int i)
{
    if (i == 0)
        return;

    NSLog(@"%d", i);
    myBlock(i - 1);
} copy];
myBlock(10);

myBlock = nil;

最佳答案

您的代码确实包含一个保留周期,但是您可以通过在递归基本情况下(myBlock)将i == 0设置为nil来中断递归结束时的保留周期。

证明这一点的最佳方法是尝试在“分配”工具下运行,关闭“停止时丢弃未记录的数据”,打开“记录引用计数”,并关闭“仅跟踪 Activity 分配”。

我使用OS X命令行工具模板创建了一个新的Xcode项目。这是整个程序:

#import <Foundation/Foundation.h>

void test() {
    __block void (^myBlock)(int) = [^void (int i){
        if (i == 0) {
//            myBlock = nil;
            return;
        }
        NSLog(@"myBlock=%p %d", myBlock, i);
        myBlock(i - 1);
    } copy];
    myBlock(10);
}

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        test();
    }
    sleep(1);
    return 0;
}

然后,使用上述设置在“分配”工具下运行它。然后在Instruments中将“统计信息”更改为“控制台”,以查看程序输出:
2012-10-26 12:04:31.391 recursiveBlockTest[71789:303] myBlock=0x7ff142c24700 10
2012-10-26 12:04:31.395 recursiveBlockTest[71789:303] myBlock=0x7ff142c24700 9
2012-10-26 12:04:31.396 recursiveBlockTest[71789:303] myBlock=0x7ff142c24700 8
2012-10-26 12:04:31.397 recursiveBlockTest[71789:303] myBlock=0x7ff142c24700 7
2012-10-26 12:04:31.397 recursiveBlockTest[71789:303] myBlock=0x7ff142c24700 6
2012-10-26 12:04:31.398 recursiveBlockTest[71789:303] myBlock=0x7ff142c24700 5
2012-10-26 12:04:31.398 recursiveBlockTest[71789:303] myBlock=0x7ff142c24700 4
2012-10-26 12:04:31.399 recursiveBlockTest[71789:303] myBlock=0x7ff142c24700 3
2012-10-26 12:04:31.400 recursiveBlockTest[71789:303] myBlock=0x7ff142c24700 2
2012-10-26 12:04:31.401 recursiveBlockTest[71789:303] myBlock=0x7ff142c24700 1
<End of Run>

我复制了块地址(0x7ff142c24700),将“控制台”更改为“对象列表”,然后将该地址粘贴到了搜索框中。仪器向我显示了该块的分配:

“实时”列下的点表示程序退出时仍在分配该块。它被泄漏了。我单击了地址旁边的箭头,以查看块分配的完整历史记录:

此分配只发生过一件事情:已分配。

接下来,我取消对myBlock = nil语句中的if (i == 0)行的注释。然后,我再次将其运行在分析器下。为了安全起见,系统随机分配了内存地址,因此我清除了搜索栏,然后再次在控制台上检查运行时该块的地址。这次是0x7fc7a1424700。我再次切换到“对象列表” View ,然后粘贴到新地址0x7fc7a1424700中。这是我所看到的:

这次,“实时”列下没有任何点,这意味着在程序退出时该块已被释放。然后,我单击了地址旁边的箭头以查看完整的历史记录:

这次,该块已分配,释放和释放。

关于objective-c - 递归块保留周期,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13090598/

10-10 08:40