Block storage types can be divided into stack type (NSStackBlock), heap type (NSMallocBlock), and global type (NSGlobalBlock).
Type determinants:
Heap type: refers to external variables and assigns block objects to strongly referenced variables or attributes
Stack type: refers to external variables, but is not strongly referenced by variables or attributes, does not count references, and is stored in the stack space
Global variables: No external variables are referenced
Survival time:
Stack type: reclaimed by autoRelease after the method that declared the block object returns
Heap type: Destroyed when the reference count becomes zero
Global type: always present and initialized at compile time
Stack type block call crashes:
A crash occurs when called after the method in which the stack block is located returns.
ViewController *vc2 = [[ViewController alloc] init];
__weak typeof(ViewController) *weakvc = vc2;
void(^__weak block)(void);
block = ^(void){
NSLog(@"%@",weakvc);
};
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
block();
});
Thread 1: EXC_BAD_ACCESS (code=1, address=0x21)
Copy the code
If it is a heap block, the heap block is referenced in dispatch_after, the reference count is +1 and no crash occurs.
When a stack block calls copy, the object returned is a block of type NSMallocBlock:
The NSStackBlock block returns a block of type NSMallocBlock after a call to copy. Since the NSStackBlock life cycle lasts until the method returns, the pointer assigned to the weak modifier is not immediately released. However, if a block of type NSMallocBlock is assigned to the weak modifier, the pointer is immediately freed.
Delayed release and circular reference of blocks of type NSMallocBlock
External variables captured within the block are referenced +1 within the block if they are __strong (or __strong by default if there is no living __weak), otherwise the reference count is not changed.
To prevent delayed release of captured objects in the block, you need to declare an __weak modifier variable that points to the object to be referenced. Using the weak pointer to capture the variable in the block does not cause delayed release.
Similarly, if the object to which the pointer to a strong reference variable is captured has a strong reference to the block, it will cause a circular reference. In this case, circular references can be avoided if the variables captured within the block are _weak qualified.