[objective-c] What does the "__block" keyword mean?

What exactly does the __block keyword in Objective-C mean? I know it allows you to modify variables within blocks, but I'd like to know...

  1. What exactly does it tell the compiler?
  2. Does it do anything else?
  3. If that's all it does then why is it needed in the first place?
  4. Is it in the docs anywhere? (I can't find it).

This question is related to objective-c ios objective-c-blocks

The answer is


__block is a storage type that is use to make in scope variables mutable, more frankly if you declare a variable with this specifier, its reference will be passed to blocks not a read-only copy for more details see Blocks Programming in iOS


__block is a storage qualifier that can be used in two ways:

  1. Marks that a variable lives in a storage that is shared between the lexical scope of the original variable and any blocks declared within that scope. And clang will generate a struct to represent this variable, and use this struct by reference(not by value).

  2. In MRC, __block can be used to avoid retain object variables a block captures. Careful that this doesn't work for ARC. In ARC, you should use __weak instead.

You can refer to apple doc for detailed information.


It means that the variable it is a prefix to is available to be used within a block.


hope this will help you

let suppose we have a code like:

{
     int stackVariable = 1;

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

it will give an error like "variable is not assignable" because the stack variable inside the block are by default immutable.

adding __block(storage modifier) ahead of it declaration make it mutable inside the block i.e __block int stackVariable=1;


@bbum covers blocks in depth in a blog post and touches on the __block storage type.

__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.
...

As for use cases you will find __block is sometimes used to avoid retain cycles since it does not retain the argument. A common example is using self.

//Now using myself inside a block will not 
//retain the value therefore breaking a
//possible retain cycle.
__block id myself = self;

Normally when you don't use __block, the block will copy(retain) the variable, so even if you modify the variable, the block has access to the old object.

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

In these 2 cases you need __block:

1.If you want to modify the variable inside the block and expect it to be visible outside:

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

2.If you want to modify the variable after you have declared the block and you expect the block to see the change:

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

From the Block Language Spec:

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.

For details on what a __block variable should compile to, see the Block Implementation Spec, section 2.3.


Examples related to objective-c

Adding a UISegmentedControl to UITableView Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Warp \ bend effect on a UIView? Use NSInteger as array index Detect if the device is iPhone X Linker Command failed with exit code 1 (use -v to see invocation), Xcode 8, Swift 3 ITSAppUsesNonExemptEncryption export compliance while internal testing? How to enable back/left swipe gesture in UINavigationController after setting leftBarButtonItem? Change status bar text color to light in iOS 9 with Objective-C

Examples related to ios

Adding a UISegmentedControl to UITableView Crop image to specified size and picture location Undefined Symbols error when integrating Apptentive iOS SDK via Cocoapods Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Autoresize View When SubViews are Added Warp \ bend effect on a UIView? Speech input for visually impaired users without the need to tap the screen make UITableViewCell selectable only while editing Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

Examples related to objective-c-blocks

Store a closure as a variable in Swift Waiting until two async blocks are executed before starting another block Assign a variable inside a Block to a variable outside a Block What does the "__block" keyword mean? How do you trigger a block after a delay, like -performSelector:withObject:afterDelay:? Can I use Objective-C blocks as properties?