What does the “__block” keyword mean?
objective-c中的
它告诉编译器,当在一个块中使用它时,它所标记的任何变量都必须以特殊的方式进行处理。通常,也会复制块中使用的变量及其内容,因此对这些变量所做的任何修改都不会显示在块外部。当它们标记为
有关示例和更多信息,请参阅Apple的Blocks编程主题中的_uuu块存储类型。
重要的例子是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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' } |
在本例中,在调用块之前修改
@bbum在博客文章中深入介绍了block,并介绍了uu 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.
...
至于用例,您会发现
1 2 3 4 | //Now using myself inside a block will not //retain the value therefore breaking a //possible retain cycle. __block id myself = self; |
_块是一个存储限定符,可以通过两种方式使用:
标记变量存在于原始变量的词法范围和该范围内声明的任何块之间共享的存储中。clang将生成一个结构来表示这个变量,并通过引用(而不是通过值)使用这个结构。
在MRC中,可以使用_uu块来避免保留块捕获的对象变量。小心这对ARC不起作用。在ARC中,您应该使用"弱"。
有关详细信息,请参阅Apple Doc。
通常,当不使用uu块时,块将复制(保留)变量,因此即使修改变量,块也可以访问旧对象。
1 2 3 4 5 6 | NSString* str = @"hello"; void (^theBlock)() = ^void() { NSLog(@"%@", str); }; str = @"how are you"; theBlock(); //prints @"hello" |
在这两种情况下,您需要块:
1.如果要修改块内的变量并希望它在块外可见:
1 2 3 4 5 6 | __block NSString* str = @"hello"; void (^theBlock)() = ^void() { str = @"how are you"; }; theBlock(); NSLog(@"%@", str); //prints"how are you" |
2.如果要在声明块后修改变量,并且希望块看到更改:
1 2 3 4 5 6 | __block NSString* str = @"hello"; void (^theBlock)() = ^void() { NSLog(@"%@", str); }; str = @"how are you"; theBlock(); //prints"how are you" |
希望这对你有帮助
假设我们有这样一个代码:
1 2 3 4 5 6 7 8 | { int stackVariable = 1; blockName = ^() { stackVariable++; } } |
它将给出一个类似"变量不可赋值"的错误,因为块中的堆栈变量在默认情况下是不可变的。
在声明之前添加uu块(存储修饰符),使其在块内可变,即
从块语言规范:
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.
有关块变量应编译为什么的详细信息,请参阅块实现规范第2.3节。
这意味着它作为前缀的变量可以在块中使用。