ios “__block”关键字是什么意思?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7080927/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What does the "__block" keyword mean?
提问by mjisrawi
What exactly does the __block
keyword in Objective-C mean? I know it allows you to modify variables within blocks, but I'd like to know...
__block
Objective-C中的关键字究竟是什么意思?我知道它允许您修改块内的变量,但我想知道......
- What exactly does it tell the compiler?
- Does it do anything else?
- If that's all it does then why is it needed in the first place?
- Is it in the docs anywhere? (I can't find it).
- 它究竟告诉编译器什么?
- 它还有别的作用吗?
- 如果这就是它所做的一切,那么为什么首先需要它?
- 它在任何地方的文档中吗?(我找不到)。
回答by DarkDust
It tells the compiler that any variable marked by it must be treated in a special way when it is used inside a block. Normally, variables and their contents that are also used in blocks are copied, thus any modification done to these variables don't show outside the block. When they are marked with __block
, the modifications done inside the block are also visible outside of it.
它告诉编译器,当它在块内使用时,任何由它标记的变量都必须以特殊方式处理。通常,也会复制块中使用的变量及其内容,因此对这些变量所做的任何修改都不会显示在块之外。当它们标有 时__block
,块内部所做的修改在块外部也是可见的。
For an example and more info, see The __block Storage Typein Apple's Blocks Programming Topics.
有关示例和更多信息,请参阅Apple 的块编程主题中的 __block 存储类型。
The important example is this one:
重要的例子是这个:
extern NSInteger CounterGlobal;
static NSInteger CounterStatic;
{
NSInteger localCounter = 42;
__block char localCharacter;
void (^aBlock)(void) = ^(void) {
++CounterGlobal;
++CounterStatic;
CounterGlobal = localCounter; // localCounter fixed at block creation
localCharacter = 'a'; // sets localCharacter in enclosing scope
};
++localCounter; // unseen by the block
localCharacter = 'b';
aBlock(); // execute the block
// localCharacter now 'a'
}
In this example, both localCounter
and localCharacter
are modified before the block is called. However, inside the block, only the modification to localCharacter
would be visible, thanks to the __block
keyword. Conversely, the block can modify localCharacter
and this modification is visible outside of the block.
在这个例子中,localCounter
和localCharacter
都在调用块之前被修改。但是,在块内localCharacter
,由于__block
关键字的存在,只有对 to 的修改是可见的。相反,块可以修改,localCharacter
并且此修改在块外部可见。
回答by Joe
@bbum covers blocks in depth in a blog postand touches on the __block storage type.
@bbum 在博客文章中深入介绍了块,并涉及 __block 存储类型。
__block is a distinct storage type
Just like static, auto, and volatile, __block is a storage type. It tells the compiler that the variable's storage is to be managed differently.
...
However, for __block variables, the block does not retain. It is up to you to retain and release, as needed.
...
__block 是一种独特的存储类型
就像静态、自动和易失性一样,__block 是一种存储类型。它告诉编译器变量的存储将以不同的方式管理。
...
但是,对于 __block 变量,块不会保留。您可以根据需要保留和释放。
...
As for use cases you will find __block
is sometimes used to avoid retain cycles since it does not retain the argument. A common example is using self.
至于用例,您会发现__block
有时用于避免保留循环,因为它不保留参数。一个常见的例子是使用 self.
//Now using myself inside a block will not
//retain the value therefore breaking a
//possible retain cycle.
__block id myself = self;
回答by Hamid Vakilian
Normally when you don't use __block, the block will copy(retain) the variable, so even if you modify the variable, the block has access to the old object.
通常,当您不使用 __block 时,block 会复制(保留)该变量,因此即使您修改了该变量,该 block 也可以访问旧对象。
NSString* str = @"hello";
void (^theBlock)() = ^void() {
NSLog(@"%@", str);
};
str = @"how are you";
theBlock(); //prints @"hello"
In these 2 cases you need __block:
在这两种情况下,您需要 __block:
1.If you want to modify the variable inside the block and expect it to be visible outside:
1.如果要修改块内的变量并期望它在外部可见:
__block NSString* str = @"hello";
void (^theBlock)() = ^void() {
str = @"how are you";
};
theBlock();
NSLog(@"%@", str); //prints "how are you"
2.If you want to modify the variable after you have declared the block and you expect the block to see the change:
2.如果要在声明块后修改变量,并且希望块看到更改:
__block NSString* str = @"hello";
void (^theBlock)() = ^void() {
NSLog(@"%@", str);
};
str = @"how are you";
theBlock(); //prints "how are you"
回答by Mindy
__blockis a storage qualifier that can be used in two ways:
__block是一个存储限定符,可以通过两种方式使用:
Marks that a variable lives in a storage that is shared between the lexical scope of the original variable and any blocks declared within that scope. And clang will generate a struct to represent this variable, and use this struct by reference(not by value).
In MRC, __blockcan be used to avoid retain object variables a block captures. Careful that this doesn't work for ARC. In ARC, you should use __weakinstead.
标记变量位于原始变量的词法范围和在该范围内声明的任何块之间共享的存储中。并且 clang 会生成一个结构体来表示这个变量,并通过引用(而不是通过值)使用这个结构体。
在 MRC 中,__block可用于避免保留块捕获的对象变量。请注意这不适用于 ARC。在 ARC 中,您应该使用__weak代替。
You can refer to apple docfor detailed information.
您可以参考苹果文档了解详细信息。
回答by mithilesh
__block
is a storage type that is use to make in scope variables mutable, more frankly if you declare a variable with this specifier, its reference will be passed to blocks not a read-only copy for more details see Blocks Programming in iOS
__block
是一种用于使作用域变量可变的存储类型,更坦率地说,如果您使用此说明符声明变量,则其引用将传递给块而不是只读副本有关更多详细信息,请参阅iOS 中的块编程
回答by Anurag Bhakuni
hope this will help you
希望能帮到你
let suppose we have a code like:
假设我们有一个类似的代码:
{
int stackVariable = 1;
blockName = ^()
{
stackVariable++;
}
}
it will give an error like "variable is not assignable" because the stack variable inside the block are by default immutable.
它会给出类似“变量不可分配”的错误,因为块内的堆栈变量默认是不可变的。
adding __block(storage modifier) ahead of it declaration make it mutable inside the block i.e __block int stackVariable=1;
在它声明之前添加 __block(storage modifier) 使其在块内可变,即 __block int stackVariable=1;
回答by Martin Gordon
From the Block Language Spec:
从块语言规范:
In addition to the new Block type we also introduce a new storage qualifier, __block, for local variables. [testme: a __block declaration within a block literal] The __block storage qualifier is mutually exclusive to the existing local storage qualifiers auto, register, and static.[testme] Variables qualified by __block act as if they were in allocated storage and this storage is automatically recovered after last use of said variable. An implementation may choose an optimization where the storage is initially automatic and only "moved" to allocated (heap) storage upon a Block_copy of a referencing Block. Such variables may be mutated as normal variables are.
In the case where a __block variable is a Block one must assume that the __block variable resides in allocated storage and as such is assumed to reference a Block that is also in allocated storage (that it is the result of a Block_copy operation). Despite this there is no provision to do a Block_copy or a Block_release if an implementation provides initial automatic storage for Blocks. This is due to the inherent race condition of potentially several threads trying to update the shared variable and the need for synchronization around disposing of older values and copying new ones. Such synchronization is beyond the scope of this language specification.
除了新的 Block 类型,我们还为局部变量引入了一个新的存储限定符 __block。[testme:块文字中的 __block 声明] __block 存储限定符与现有的本地存储限定符 auto、register 和 static 是互斥的。上次使用该变量后自动恢复。实现可以选择一种优化,其中存储最初是自动的,并且仅在引用块的 Block_copy 时“移动”到分配的(堆)存储。此类变量可能会像正常变量一样发生突变。
在 __block 变量是 Block 的情况下,必须假设 __block 变量驻留在分配的存储中,因此假设引用也在分配的存储中的 Block(它是 Block_copy 操作的结果)。尽管如此,如果实现为块提供初始自动存储,则没有规定执行 Block_copy 或 Block_release。这是由于潜在的多个线程试图更新共享变量的固有竞争条件以及围绕处理旧值和复制新值的同步需要。这种同步超出了本语言规范的范围。
For details on what a __block variable should compile to, see the Block Implementation Spec, section 2.3.
有关 __block 变量应编译为什么的详细信息,请参阅块实现规范,第 2.3 节。
回答by Rich Allen
It means that the variable it is a prefix to is available to be used within a block.
这意味着作为前缀的变量可以在块中使用。