int anInteger = 42;
void (^testBlock)(void) = ^{
NSLog(@"Integer is: %i", anInteger);
};
anInteger = 84;
testBlock();
Integer is: 42
这是Apple官方指南中的一个例子。
现在,对于对象值,它很容易理解,它会保留对它的引用。所以稍后,当它的原始引用更改为指向其他内容时,或者只是被销毁。此引用仍然存在,因此引用计数不会为零,并保留原始值。
但是,对于上面的示例代码,它不是一个对象。该块保留对它的引用,然后该值更改为84.我认为这是对自身的更改而不是其副本,这意味着指针指向的值已更改。怎么还能42岁?
答案 0 :(得分:9)
从文档的Blocks and Variables部分:
以下规则适用于块中使用的变量:
- 可以访问全局变量,包括存在于封闭词法范围内的静态变量。
- 可以访问传递给块的参数(就像函数的参数一样)。
- 封闭词法范围本地的堆栈(非静态)变量被捕获为const变量。 它们的值是在程序中的块表达点处获取的。在嵌套块中,从最近的封闭范围捕获值。
- 使用__block存储修饰符声明的封闭词法范围的局部变量由引用提供,因此是可变的。 任何更改都会反映在封闭的词法范围中,包括在相同的封闭词法范围内定义的任何其他块。这些将在__block Storage Type。
中详细讨论- 在块的词法范围内声明的局部变量,其行为与函数中的局部变量完全相同。 每次调用块都会提供该变量的新副本。这些变量又可以在块中包含的块中用作const或by-reference变量。
醇>
规则3适用于您问题中的代码。
答案 1 :(得分:1)
块引入必要的间接以确保发生这种情况。看似本地但由块捕获的变量实际上是由编译器在堆上分配的。除此之外,这对于该变量能够比其声明的函数的生命周期更长是必要的。
答案 2 :(得分:1)
简而言之:复制整数值。 (更确切地说:结构和对象引用也被复制。但是在对象引用的情况下,它是一个引用。)
顺便说一句:这就是封闭的含义。这就是关闭的原因。他们存在的原因。您想要这个行为。否则,您必须确保在块运行时不会更改值 - 可能是几秒或几分钟。