First, solve the circular reference
I Basic controller code:
#import "ViewController.h"
///The first two solve circular references
typedef void(^CPBlock)(void);
///Used for the third solution to circular references
typedef void(^CPParamBlock)(ViewController *);
@interface ViewController ()
///The first two solve circular references示例
@property(nonatomic, copy) CPBlock block;
///Used for the third solution to circular references示例
@property(nonatomic, copy) CPParamBlock paramBlock;
@property(nonatomic, copy) NSString *name;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.name = @"CPBlock";
}
@end
II Block circular reference example code
//1. Self holding block
self.block = ^(void){
//Block hold self
NSLog(@"%@", self);
//Block hold self的属性name
NSLog(@"%@", self.name);
};
- When self wants to release itself, it needs to release the block first,
- To release the block, first release the holding of self in the executive body block,
- Self’s retaincount= 0, self. Retain count of block= 0, both will never be released, resulting in circular reference
Three key points — solving circular application
Method 1 Weak reference method to solve circular application code__ weak
-(void)resolveRetainCycle_1{
__weak typeof(self) weakSelf = self;
self.block = ^(void){
NSLog(@"%@", weakSelf);
//If there are time-consuming operations or asynchronous operations in the block execution body, we also need to optimize the solution of circular reference
//Strongself is a local variable in the block executor. It is used within the scope of the block executor. When the block is released, strongself will also be released automatically
__strong typeof(weakSelf)strongSelf = weakSelf;
//This asynchronous task with a delay of 2 seconds simulates time-consuming operations
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%@", strongSelf.name);
});
};
self.block();
}
Method 2 Intercepting variable mode__ block
-(void)resolveRetainCycle_2{
//Intercept the current viewcontroller
//Need to release VC = nil manually;
__block ViewController *vc = self;
self.block = ^(void){
//This asynchronous task with a delay of 2 seconds simulates time-consuming operations
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%@", vc.name);
vc = nil;
});
};
self.block();
}
Method 3 Communication value transmission mode
///Three methods to solve circular reference
-(void)resolveRetainCycle_3{
//Pass self (actually the current controller: viewcontroller) as a temporary variable into the block execution body
//Does not cause circular references
self.paramBlock = ^(ViewController *vc){
//This asynchronous task with a delay of 2 seconds simulates time-consuming operations
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%@", vc.name);
});
};
self.paramBlock(self);
}