"__block"关键字是什么意思?

mji*_*awi 435 objective-c ios objective-c-blocks

__blockObjective-C 中的关键字究竟是什么意思?我知道它允许你修改块内的变量,但我想知道......

  1. 它究竟是什么告诉编译器的?
  2. 它还有什么用吗?
  3. 如果就是这样,那么为什么首先需要呢?
  4. 是在任何地方的文档?(我找不到).

Dar*_*ust 530

它告诉编译器在块中使用它时,必须以特殊方式处理由它标记的任何变量.通常,也会复制块中也使用的变量及其内容,因此对这些变量所做的任何修改都不会显示在块之外.当它们被标记时__block,在块内部进行的修改也在其外部可见.

有关示例和更多信息,请参阅Apple的块编程主题中的__block存储类型.

这个重要的例子是:

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'
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,在调用块之前修改了localCounterlocalCharacter.但是,在块内部localCharacter,由于__block关键字,只能看到修改.相反,块可以修改,localCharacter并且此修改在块外部可见.

  • 它不会修改`localCounter`,但会修改`localCharacter`.另外,要注意块中的"localCounter"值:它是42,即使变量在调用块之前*增加*但是*在创建块之后*(当值被"捕获"时). (8认同)
  • 优秀,简洁的解释,一个非常有用的例子.谢谢! (7认同)
  • 通常,在创建该块时,不带__block的var将按值捕获并打包到该块的“环境”中。但是__block vars不会被捕获,无论何时在块的内部或外部使用它们,都按原样引用它们。 (2认同)

Joe*_*Joe 27

@bbum在博客文章中深入介绍了块,并触及__block存储类型.

__block是一种独特的存储类型

就像静态,自动和易失性一样,__block是一种存储类型.它告诉编译器变量的存储将以不同方式进行管理.

...

但是,对于__block变量,块不会保留.您可以根据需要保留和释放.
...

对于用例,您会发现__block有时用于避免保留周期,因为它不保留参数.一个常见的例子是使用self.

//Now using myself inside a block will not 
//retain the value therefore breaking a
//possible retain cycle.
__block id myself = self;
Run Code Online (Sandbox Code Playgroud)

  • 最后声明__block可以用来避免强引用周期(也就是保留周期)在ARC上下文中是完全错误的.由于ARC __block导致变量被强引用,实际上更有可能导致变量.http://stackoverflow.com/a/19228179/189006 (16认同)

Min*_*ndy 8

__block是一个存储限定符,可以通过两种方式使用:

  1. 标记变量存在于原始变量的词法范围与该范围内声明的任何块之间共享的存储中.并且clang将生成一个表示此变量的结构,并通过引用(而不是值)使用此结构.

  2. 在MRC中,__block可用于避免块捕获保留对象变量.小心这对ARC不起作用.在ARC中,您应该使用__weak.

您可以参考apple doc获取详细信息.


Ham*_*ian 8

通常,当您不使用__block时,该块将复制(保留)该变量,因此即使您修改了该变量,该块也可以访问旧对象.

NSString* str = @"hello";
void (^theBlock)() = ^void() {
    NSLog(@"%@", str);
};
str = @"how are you";
theBlock(); //prints @"hello"
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,您需要__block:

1.如果你想修改块内的变量并希望它在外面可见:

__block NSString* str = @"hello";
void (^theBlock)() = ^void() {
    str = @"how are you";
};
theBlock();
NSLog(@"%@", str); //prints "how are you"
Run Code Online (Sandbox Code Playgroud)

2.如果要在声明块后修改变量,并且希望块看到更改:

__block NSString* str = @"hello";
void (^theBlock)() = ^void() {
    NSLog(@"%@", str);
};
str = @"how are you";
theBlock(); //prints "how are you"
Run Code Online (Sandbox Code Playgroud)


mit*_*esh 6

__block是一种存储类型,用于使范围变量可变,更坦率地说,如果使用此说明符声明变量,其引用将传递给块而不是只读副本以获取更多详细信息,请参阅iOS中的块编程