What is a Block?

A Block is an object that encapsulates a function and its execution context. Such as:

M file is compiled using the clang-rewrite-objc wytest. m command, and we find that the block is compiled to this form:

Where WYTest is the file name and blockTest is the method name, these can be ignored. The WYTest blockTest_block_impl_0 structure is

The block_impl structure is

A block has an ISA pointer inside it, so it is essentially an OC object

Inside the block, it is:

So a Block is an object that encapsulates a function and its execution context

Since a block encapsulates a function internally, it also has parameters and return values.

2. Block variable interception

1. Local variable interception is value interception. Such as:

The output here is 6 instead of 2 because the interception of the local variable num is a value interception. Similarly, changing the num variable in a block is invalid, and the compiler may even report an error.

Print as 1,2,3

Same thing with a local object variable, which intercepts a value, not a pointer, and externally sets it to nil, which has no effect on the block, whereas the method that the object calls does

2. Local static variable interception is pointer interception.

The output is 2, which means num = 1. The change in num is valid, that is, pointer interception. It is also valid to modify the m variable in the block.

First of all, as a developer, there is a learning atmosphere with a communication circle is particularly important, this is xin an iOS development public number: programming Xin, whether you are small white or bull are welcome to enter, let us progress together, common development! (The group will provide some free learning books collected by the group owner and hundreds of interview questions and answer documents!)

##3, global variable, static global variable interception: do not intercept, direct value. Let’s also compile with clang to see the results.

The compiled

(impl. Isa = & _NSConcreteStackBlock; This block is a stack block.

You can see that local variables are compiled as values, and static variables are compiled as Pointers. Global variables are not intercepted. A variable modified by –block is also intercepted as a pointer, and a new struct object is generated:

This object has a property: num5, which is the variable we decorate with –block. Here –forwarding refers to itself (stack block).

In general, we need to add the –block modifier to local variables that block intercepts. We do not need to add the –block modifier to global or static variables.

In addition, any access to self in a block or to a member variable will intercept self.

Three, several forms of Block

There are global blocks (_NSConcreteGlobalBlock), stack blocks (_NSConcreteStackBlock), and heaps

Block(_NSConcreteMallocBlock) has three forms

Stack blocks are stored in the stack area, heap blocks are stored in the heap area, and global blocks are stored in the initialized data area

##1: A block that does not use external variables is a global block.

Output:

A block that uses an external variable and is not copied is a stack block

Such as:

Output:

Everyday development is often used in situations like this:

##3: Copy a stack block; copy a global block

For example, a global copy in heap 1 is assigned:

Output:

Still a global block

Assign to stack block in 2:

Output:

After the stack blockcopy, it does not mean that the stack block disappears. The left mallock is the heap block, and the right copy is still the stack block.

Output:

That is, if you cop a stack Block, it will copy to the heap, if you copy a heap Block, it will increase the reference count, if you copy a global Block, because it’s already initialized, it will do nothing.

In addition, when the –block variable is copied, the –forwarding pointer on the stack points to the –forwarding variable on the heap, and the –forwarding pointer on the heap points to itself, so, If you modify the –block, you’re actually modifying the –block variable on the heap.

The meaning of the –forwarding pointer is that the same –block variable can be accessed from any location in memory.

In addition, since the variables captured by the block will hold the variables, if you use the –block to decorate self, and self holds

Block, and the use of a — block-decorated self inside a block causes multiple circular references, that is, self holds a block, block holds a –block variable, and –block holds self, causing a memory leak.

Such as:

If you want to solve this circular reference, you can actively disconnect the block variable from holding self, that is, after using weakSelf inside the block, set it to nil, but this way has a problem, if the block has not been called, then the circular reference will always exist.

So it’s better to use –weak to describe self

Thank you for watching!