什么时候不在Objective-C中使用__block?

Jos*_*lar 9 objective-c ios objective-c-blocks

使用块时,为什么某些变量需要__block,而其他变量(如函数参数)则不需要?

Cat*_*Man 24

问题的确是以错误的方式表达的.它不是"我什么时候需要__block?",它是"__block做什么?".一旦了解了它的作用,就可以知道何时需要它.

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

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

int x = 5;
void(^block)() = ^{ x = 10; };
Run Code Online (Sandbox Code Playgroud)

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


Chr*_*s C 14

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

编辑:这是一个例子:

NSString *myString = @"hello";
dispatch_sync(dispatch_get_main_queue(), ^{
    myString = @"hello world";
});
Run Code Online (Sandbox Code Playgroud)

这不起作用,您将收到错误消息.

__block NSString *myString = @"hello";
dispatch_sync(dispatch_get_main_queue(), ^{
    myString = @"hello world";
});
Run Code Online (Sandbox Code Playgroud)

问题解决了!