First, where is the block placed
We discuss the storage location of blocks for different situations:
1. Stacks and heaps
Blocks are located in the heap in the following cases:
Void foo () { __block int i = 1024; int j = 1; void (^ BLK) (void); void (^blkinheap) (void); blk = ^{ printf ("%d, %d\n", i, j);};/ /blk in the stack blkinheap = block_copy (BLK);//blkinheap in the heap } - (void) foobar { _oi = 1; OBJ1* oj = self; void (^OBLK) (void) = ^{ printf ("%d\n", oj.oi);}; void (^oblkinheap) (void) = [oblk copy];//oblkinheap in the heap }
2. Global Zone
The block in the following scenario is in the global zone:
static int (^maxintblock) (int, int) = ^ (int a, int b) {return a>b?a:b;}; -(void) FooBar {int (^maxintblockcopied) (int, int) =[maxintblock copy]; } void foo () {int (^maxintblockcopied) (int, int) = Block_copy (Maxintblock); }
It is important to note that the block after the copy is still in the global zone, in fact, the copy operation is directly returned to the original block object.
Ii. where are the variables referenced by the block
1. Global Zone
The variable storage location of the global zone is independent of the BLOCK:
static int gVar = 0; __block static int gmvar = 1; void foo () {static int stackvar = 0; __block static int stackmvar = 0; }
Note:The static variable is not allowed to add the __block tag
2. Stacks
At this point, you might ask, when the function foo returns, J on the stack has been recycled, so how can blkinheap continue to use it? This is because there is no __block tag of the variable, will be used as an argument into the block's underlying implementation function, when the code in the block is executed, J is not the original J, so-called is the same thing ~
Also, if all blocks using the variable J are not copied to the heap, then the variable J will not be copied to the heap.
Thus, even before the sentence of J + + is put to BLK (), after this code executes, the console prints the result: 1024, 1. Instead of 1024, 2
Third, other characteristics
1. Behavior of replication
There are several scenarios in which the block call replication:
1. The block call to copy on the global zone returns the original pointer and does not process anything during this time (at least the current internal implementation is so);
2. The block on the stack is called copy, each time it returns a pointer to a block that is newly copied to the heap, and all __block variables are copied to the heap (multiple copies, only one copy is generated).
3. Calling copy again for blocks already on the heap will only increase the reference count of the block.
Why don't we discuss Retian's behavior? The reason is that there is no such function, and the internal implementation of the retain message sent to the Block object in OBJC is Block_retain.
Block replication in the 2.OBJC class
If the block in the OBJC class instance method is copied to the heap, the current instance is incremented by the reference count, which is reduced when the block is freed.
However, if the block does not use any of the members of the current instance, then the current instance is not incremented by the reference count. This is also very natural reason, since I did not use this instance anything, then why should I retian it?
One thing we should be aware of is that I see a lot of people on the internet saying that block causes a circular reference between the instance and the Block (retain-cycle), and gives the solution: instead of using self directly, assign self to a temporary variable before using the temporary variable.
However, it is important to note that we must add __block tags to this temporary variable
Introduction to block in iOS (ii) memory management and other features