10

使用block的时候,为什么有些变量需要__block,而其他变量,比如函数参数,你不需要呢?

4

2 回答 2

30

这个问题的措辞确实是错误的。这不是“我什么时候需要 __block?”,而是“__block 做什么?”。一旦你了解了它的作用,你就可以知道什么时候需要它。

通常,当一个块捕获一个变量时(捕获发生在一个块引用自身外部的变量时),它会创建该变量的副本(注意,在对象的情况下,它会创建指针的副本而不是对象本身),并且如果它是一个对象,则保留它。

这意味着在正常行为下,您不能使用块来更改块外的值。此代码无效,例如:

int x = 5;
void(^block)() = ^{ x = 10; };

__block 限定符做了两个改变:最重要的是,它告诉编译器该块应该直接捕获它,而不是复制。这意味着您可以更新块外变量的值。不太重要,但仍然非常相关,当不使用 ARC 时,它告诉编译器不要保留捕获的对象。

于 2013-02-07T19:13:45.490 回答
15

代码块可以访问在块被声明的范围内的任何变量。但是,在块范围之外声明的任何变量/对象在块内都是不可变的。你可以阅读它,但不能改变它。在对象的声明中设置 __block 标志允许在块的范围内对其进行更改。

编辑:这是一个例子:

NSString *myString = @"hello";
dispatch_sync(dispatch_get_main_queue(), ^{
    myString = @"hello world";
});

这不起作用,您将收到一条错误消息。

__block NSString *myString = @"hello";
dispatch_sync(dispatch_get_main_queue(), ^{
    myString = @"hello world";
});

问题解决了!

于 2013-02-07T19:13:18.963 回答