A thorough understanding of iOS block knowledge points in one article

Estimated read time 10 min read

You can read this article with the following questions

Basic questions

  1. What is Block? Please give an example of Block usage scenarios.
  2. How does Block capture external variables? Please explain the rules for Block capture variables.
  3. Please explain Block memory management, especially the difference between non-ARC and ARC environments.

Advanced questions

  1. __blockWhat do modifiers do? What are the precautions for using it?
  2. Please explain the three types of Blocks and their characteristics.

Advanced questions

  1. Please explain the underlying implementation principle of Block, including how to copy from stack to heap.
  2. __forwardingWhat is the role of pointers? How does it support __blockmemory management of variables?
  3. Why should we design __block, __frowarding, and what is its principle?

1. What is a block? What is a Block call?

  • Block is an object that encapsulates a function and its context . Block calls are both function calls.

2. Block memory structure

Block is an Objective-C object under the hood, and its memory structure contains the following main parts:

  1. Block object header :
    • isaPointer: A pointer to the Block class, indicating that this is an object.
    • flags: Used to represent some attributes of Block, such as whether it has been copied to the heap, whether there are captured external variables, etc.
    • reserved: Reserved field, currently unused.
    • invoke: Function pointer, pointing to the execution code of the Block, that is, the implementation of the Block body.
  2. Block description information ( descriptor):
    • size: The size of the Block structure.
    • copy_helperand dispose_helper: When the Block is copied from the stack to the heap, these two function pointers are used to manage the memory of the captured external variables (if any).
    • signature: Block signature information, used to describe Block parameters and return value types (optional).
  3. Captured external variables :
    • Block captures local variables in the scope in which it is defined. Copies or references to these variables are stored immediately after the Block object header and description information.
  4. Memory structure example

Suppose there is the following Block definition:

int a = 10;
void (^myBlock)(void) = ^{
    NSLog(@"Value of a: %d", a);
};

Its memory structure is roughly as follows:

+----------------------+
|       isa        |
+----------------------+
|       flags         |
+----------------------+
|      reserved       |
+----------------------+
|      invoke         |
+----------------------+
|    descriptor       |
|      - size         |
|      - copy_helper  |
|      - dispose_helper|
|      - signature    |
+----------------------+
|   a   |
+----------------------+

3. Block memory management

1. Three types of Blocks

There are three types of Blocks in memory, and their memory management methods are different:

  • _NSConcreteGlobalBlock : Global Block, stored in the global data area, no manual memory management is required.
  • _NSConcreteStackBlock : Stack Block, stored on the stack, will be automatically destroyed when leaving the scope in which it is defined.
  • _NSConcreteMallocBlock : Heap Block, stored on the heap, requires manual memory management (in non-ARC environment).

When a Block is copied, different types of Blocks will have different behaviors and changes:

  1. Global Block (_NSConcreteGlobalBlock)
  • Global Block is stored in the global data area and does not capture any external variables.
  • When the global Block is copied, no real memory copy operation actually occurs, but the pointer to the Block itself is simply returned. Therefore, the copy of the global Block will not cause any memory or state changes.
  1. Stack Block (_NSConcreteStackBlock)
  • Stack Block is stored on the stack and may capture external variables.
  • When the stack Block is copied to the heap (for example, through the Block_copy function or assigned to a strong reference under ARC), the following changes occur:
    • Allocate heap memory for the Block and copy the contents of the stack Block (including captured external variables) to the new location on the heap.
    • If Block captures __blockvariables, these variables will also be copied to the heap together, and their __forwardingpointers will be updated to ensure that subsequent accesses and modifications to these variables point to the copies on the heap.
    • The copied Block becomes a heap Block (_NSConcreteMallocBlock), and its life cycle is managed by reference counting.
  1. Heap Block (_NSConcreteMallocBlock)
  • Heap Block is stored on the heap, and its life cycle is managed by reference counting.
  • When a heap block is copied, in an ARC environment, the reference count is incremented, but no actual memory copy operation occurs. In a non-ARC environment, you need to manually manage Block reference counting and memory release.

Summarize:

  • When the Block is copied, the global Block will not change. The Stack Block will be copied to the heap and become a Heap Block, and the reference count of the Heap Block will increase.

4. block capture variables

In Objective-C, a Block can capture variables external to the scope in which it is defined. This feature enables the Block to access and use variables defined outside of it. The following are some details of Block capturing external variables:

Capture method

  1. Basic data type variables : For local variables of basic data types (such as int, float, etc.), Block captures a copy of their value. This means that modifications to these variables within the Block will not affect the values ​​of the original variables.int value = 10; void (^myBlock)(void) = ^{ NSLog(@"Value inside block: %d", value); }; value = 20; myBlock(); // "Value inside block: 10" In this example, valuethe value inside the Block is still 10, even though valueit is modified to 20 outside the Block.
  2. Object type variables : For local variables of object type, Block captures a strong reference to the object. This means that the properties of the object can be accessed and modified inside the Block, and these modifications will be reflected on the original object.NSMutableArray *array = [NSMutableArray arrayWithObjects:@"a", @"b", nil]; void (^myBlock)(void) = ^{ [array addObject:@"c"]; }; myBlock(); NSLog(@"Array: %@", array); // "Array: (a, b, c)" In this example, arraythe Block is modified inside and a new element “c” is added.

Summarize

Blocks’ ability to capture external variables makes them very flexible and powerful, especially in asynchronous programming and callbacks. A proper understanding of how Blocks capture and use external variables is important to writing correct and efficient code.

5. How block modifies external variable values: __block

__blockExample of

If you need to modify the value of a local variable of a basic data type inside the Block, you can use __blockmodifiers. This way, the Block captures the variable by reference rather than by value, allowing the variable to be modified within the Block.

__block int value = 10;
void (^myBlock)(void) = ^{
    value = 20; //  __block 
};
myBlock();
NSLog(@"Value: %d", value); //  "Value: 20"

In this example, using __blockthe modifier allows the Block to modify valuethe value of .

__blockWhat is it?

In Objective-C, __blockit is a storage type modifier used to modify variables used in Block. When a variable is __blockmodified, it allows modification of the variable within the Block.

principle

  1. Encapsulated into a structure : __blockVariables modified with will be encapsulated into a structure by the compiler. This structure contains the value of the variable and a __forwardingpointer to support the process of copying the variable from the stack to the heap.
  2. Reference capture : Unlike ordinary local variables captured by value, __blockvariables are captured by reference. This means that the Block internally accesses __blockthe variable’s address, not its copy.
  3. Stack-to-heap copying : When a Block is copied to the heap (for example, assigned to a strongly referenced variable or returned as a function value), all variables captured by the Block __blockare also copied to the heap. During the copying process, __forwardingthe pointer is updated to point to the copy of the variable on the heap.

Why is it needed __block?

  1. Modify external variables : Without __blockthe modifier, Block can only capture the values ​​of external variables but cannot modify these variables. __blockAllows modifying the value of external variables inside the Block.
  2. Support the life cycle of variables : When the Block is copied to the heap, __blockthe variables will also be copied to the heap to ensure that the variables are still valid during the life cycle of the Block.
  3. Simplified memory management : In an automatic reference counting (ARC) environment, __blockmemory management of variables is automatically handled, including memory management when variables are copied to the heap.
  4. Adapt to asynchronous programming mode : In asynchronous programming, it is often necessary to modify external variables in Block to store the results of asynchronous operations. __blockMakes this model easier to implement.

In general, __blockmodifiers are used to enhance the functionality of Block so that it can modify captured external variables. This is useful in asynchronous programming, callback handling, and other scenarios where external state needs to be modified in a Block. Understanding __blockthe principles and functions of helps to use Block and manage memory more effectively.

6.__forwarding

__forwarding__blockIs a mechanism related to variables in Objective-C . It is __blocka pointer in the variable structure and is used to ensure that access and modification of the variable can be performed correctly regardless of whether the variable is on the stack or the heap.

principle

  1. __blockEncapsulation of variables : __blockVariables declared using the modifier will be encapsulated by the compiler into a structure that contains the value of the variable and a __forwardingpointer.
  2. The pointer points to itself : Initially, the pointer __blockof the variable __forwardingpoints to the variable itself (that is, to the structure itself).
  3. Copied to the heap : When the Block is copied to the heap, all variables captured by the Block __blockwill also be copied to the heap. At this point, __forwardingthe pointer will be updated to point to the copy of the variable on the heap.
  4. Uniform access method : Regardless of whether __blockthe variable is on the stack or the heap, access and modification to it __forwardingare performed through pointers. This ensures that variable accesses and modifications always point to the correct storage location.

why needed__forwarding

  1. Maintain access consistency : __forwardingThe mechanism ensures that the access and modification of variables in the Block __blockare always consistent, regardless of whether the variables are on the stack or the heap.
  2. Supports stack-to-heap migration : When Blocks and __blockvariables are copied from the stack to the heap, __forwardingpointers make the variable migration process smoother. It keeps the reference to the variable unchanged even if the variable’s storage location changes.
  3. Simplified memory management : __forwardingThe mechanism simplifies __blockmemory management when variables are migrated between stack and heap. Developers do not need to care about the specific storage location of variables, they only need __forwardingto access and modify them through pointers.

In general, __forwardingit is __blockan important part of the variable mechanism, which ensures __blockaccess consistency and simplified memory management when using variables in Block. Understanding __forwardingthe principles and functions of helps to have a deeper understanding of __blockthe working mechanism of Block and variables.

Summarize

__blockThe principle of modifiers involves __blockthe storage method, capture mechanism and internal structure of variables. By encapsulating variables as structures and capturing them by reference, __blockthe value of external variables is allowed to be modified in the Block. When the Block is copied to the heap, __forwardingthe pointer ensures that the access and modification of variables are carried out through the same address, ensuring the consistency and correctness of the data.

You May Also Like

More From Author

+ There are no comments

Add yours