是否有必要对块中更改的可变对象使用__block类型说明符?

时间:2017-02-19 18:34:23

标签: objective-c block

说地图是一个NSDictioanry,我的理解是因为res的地址在块中没有改变我们不需要使用__block。它是否正确?

//__block NSMutableArray *res = [@[] mutableCopy];
NSMutableArray *res = [@[] mutableCopy];
__block NSInteger i = 0;
[map enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSArray *v, BOOL *stop) {
    [res addObject:v];
    i++;
}];

顺便说一下,我运行代码就可以了。

2 个答案:

答案 0 :(得分:3)

__block类型说明符仅用于存储通常存在于堆栈中的可变项。

由于不能保证只在创建它的方法范围内调用一个块(这称为转义),它可能需要改变它们在它们消失后引用的变量。如果块被保持在原始方法或函数的末尾,那么对堆栈中的内容的引用(如示例中的i)可能会成为悬空指针,因此如果它们要进行变异,则需要存储在堆栈以外的其他地方。 __block说明符告诉编译器将变量放在单独的存储器中,只要调用块就会有效。

对于堆分配的东西(如上面的res),这不是必需的 - 因为只要对象在周围,指向对象的指针就不会改变(它应该是,因为块将默认情况下保留它),对象指针的本地存储不需要放在备用存储中,并且可以保留在堆栈中。

如果您想了解更多信息,Blocks and Variables文档页面提供了有关使用块的内存管理的详细信息,以及有关__block存储类型的更多信息。

答案 1 :(得分:0)

这是正确的。仅当您为块内的变量分配(__block或等效项)时,或者如果要阻止在块创建后才能看到块外部变量的赋值,则=是必需的。 (无论变量的类型是什么,都是如此。)

此处,使用i运算符将变量++分配给块内部,因此__block是必需的。变量res永远不会分配给任何地方;变量res 中读取(未分配给)。