Guide language: today we discuss block, exactly is how to work, some things may be bad to understand, but I think, clear that several key line, the first block, how to use (all used, he said a few), variable how to capture, block, how to modify the external variables, how not to form a circular reference is basic. If you are interested, you can learn more about it. In addition, my knowledge reserve is limited, if there are mistakes, please be sure to correct, thank you very much.

The block definition

  • A block is essentially an OC object

  • A block is an OC object that encapsulates the implementation of a function and the environment in which the function is called, and itself has an ISA pointer

The underlying structure diagram of block is as follows:

Block_layout Block_descriptor
(void*) isa (unsighed long int) reserved
(int) flags (unsighed long int) size
(int) reserved (void *(void *)) copy
(void *(void *, …) ) invoke (void *(void *)) dispose
(strut Block_descriptor *) descriptor descriptor -> Block_descriptor
variables

Block variable capture

  • If you want to use local variables inside a block, you first need to capture local variables
Block direct reference Block variable capture
The global variable Auto modified local variable (value capture, internally create a new local variable)
Function arguments (including self, _cmd hidden arguments)
Static modified local variables (capture Pointers)

Local variable without modifier, default is auto modifier.

If a block in a method uses self, or any other argument to the function, the block captures those variables.

If it is an auto modified local variable, the block directly captures the value of the local variable and generates a new variable with the same name inside the block to store the local variable.

If it is a static modified local variable, block captures a pointer to the layout variable

If it is a global variable, whether static or not, it is not captured and referenced directly

  • Why not just capture the pointer to the auto-modified local variable?

This is because the auto-modified local variable is destroyed out of scope. It is possible to call the block after the destruction of the local variable. If the pointer is captured directly, a wild pointer error will be generated. Local variables that are static can be accessed through Pointers.


Block type

Block type Storage location
__NSGlobalBlock__ Data segments exist
__NSStackBlock__ There is stack area (easy to destroy, to keep the copy to the heap area)
__NSMallocBlock__ Heap zone

__NSGlobalBlock__ : Any block that does not capture an auto modifier is of type NSGlobalBlock (including any block that captures a static modifier).

__NSStackBlock__ : Blocks that capture auto-modified local variables are of type NSStackBlock

__NSMallocBlock__ : A block call to copy from __NSStackBlock__ generates a block of type __NSMallocBlock__

Block of copy

  • In ARC auto-managed memory mode, copy is automatically invoked whenever there is a strong pointer to a block
  • Block also reverses copy when it returns a function value
  • Block is used as a Cocoa API method name containing a method parameter called usingBlock
  • Block as a method parameter of the GCD API
@property (copy, nonatomic) void (^block)(void); @property (copy, nonatomic) void (^block)(void); @property (strong, nonatomic) void (^block1)(void); @property (copy, nonatomic) void (^block2)(void);Copy the code

The auto variable of object type

  • If the block is on the stack, the block does not generate a strong reference (because the block can be destroyed at any time), regardless of whether the auto variable of an object is strong.

  • If a block is copied to the heap

  1. The copy function inside the block is called
  2. Copy is called internally_Block_object_assignfunction
  3. _Block_object_assignThe function is based on the auto modifier (__strong,__weak,__unsafe_unretained) to form a strong or weak reference

In short, the block internally reacts to the modifier of the auto variable to form a strong or weak reference

  • Copy and dispose functions are added inside the block that is copied

Copy functions on the stack copy to the heap

Called when a block on the dispose heap is discarded


__blockThe modifier

__blockModify variables

Blocks cannot modify external local variables by default.

Only local variables decorated with __block can be modified inside a block.

The __block modifier can only be used to modify auto-modified variables.

  • The principle of __block revaluating is that an auto variable is decorated with __block. The compiler wraps the variable into an object (the previous auto variable becomes a member variable in the object) and modifies the value through the address pointer.

  • Memory management: In principle, as with auto, there is no strong reference to __block-modified variables if blocks are on the stack, and strong reference to __block-modified variables if blocks are copied to the heap.

  • Internal block is called when a block is removed from the heap

Dispose ->_Block_object_dispose-> Automatically releases the __block modified variableCopy the code

Summary: A variable decorated with __block can be treated as an object, so its value can be modified by a pointer.

__blockModify the object

  • If a __block variable is on the stack, there is no strong reference to the object to which it points.

  • When a __block variable is copied to the heap

The copy function inside the __block variable is called, and the _Block_object_assign function is called inside the copy function.

The _Block_object_assign function provides retained or weak references based on the __strong, __weak, and __unsafe_unretained modifiers. This is limited to retain with ARC and not with MRC).

  • if__blockVariables are removed from the heap.

Dispose function inside the __block variable is called.

The _Block_object_dispose function is called internally.

The _Block_object_dispose function automatically releases the object it points to.


Block loop reference

  • In development, we often encounter block circular references.

The classic circular reference is when a block is strongly referenced by an object as a property, and inside the block is self, which in turn strongly references the object.

__weak (__weak typeof(self) weakSelf = self) and __unsafe_unretained are commonly used to solve this problem.

We can also use __block to solve the problem of circular references, but block must be called. (It’s good to know that __block also does this, and you should use __weak in your development).

Circular reference to this problem, there is a lot of information on the Internet, not to say here.

  • Some materials are quoted from the Internet. If you don’t understand or make mistakes, please point them out directly. We will discuss them together.

What is it like to create a serial-oc object

What is the flow of series -OC method call

How is series – KVO&KVC realized

On the structure and loading time of series-classification

Brief introduction to series-load and initialize call timing and practical use