Objective-C中的__block关键字到底是什么意思?我知道它允许你在块内修改变量,但我想知道…

它到底告诉编译器什么? 它还有别的功能吗? 如果这就是它所做的一切,那么为什么首先需要它呢? 文档里有吗?(我找不到)。


当前回答

@bbum在一篇博客文章中深入介绍了块,并涉及到__block存储类型。

__block是一种独特的存储类型 就像static、auto和volatile一样,__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;

其他回答

希望这对你有所帮助

让我们假设我们有这样一个代码:

{
     int stackVariable = 1;

     blockName = ^()
     {
      stackVariable++;
     }
}

它会给出一个类似“变量不可赋值”的错误,因为块内的堆栈变量默认是不可变的。

在它的声明之前添加__block(存储修饰符),使它在块内部是可变的,即__block int stackVariable=1;

__block是一种存储类型,用于使作用域变量可变,更坦率地说,如果你声明一个变量与此说明符,它的引用将被传递给块而不是只读副本,详情请参阅iOS中的块编程

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

标记变量位于原始变量的词法作用域和在该作用域中声明的任何块之间共享的存储中。clang将生成一个表示该变量的结构体,并通过引用(而不是值)使用该结构体。 在MRC中,__block可用于避免保留块捕获的对象变量。注意这对ARC不起作用。在ARC中,你应该使用__weak。

你可以参考苹果文档的详细信息。

它告诉编译器,当它在块中使用时,任何被它标记的变量都必须以特殊的方式处理。通常情况下,在块中使用的变量及其内容会被复制,因此对这些变量所做的任何修改都不会在块外显示。当它们被标记为__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'
}

在这个例子中,在调用块之前,localCounter和localCharacter都被修改了。然而,在块内部,由于__block关键字,只有对localCharacter的修改是可见的。相反,块可以修改localCharacter,并且这种修改在块外部是可见的。

@bbum在一篇博客文章中深入介绍了块,并涉及到__block存储类型。

__block是一种独特的存储类型 就像static、auto和volatile一样,__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;