IOS block solves circular reference

Time:2022-5-4

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);
    };
  1. When self wants to release itself, it needs to release the block first,
  2. To release the block, first release the holding of self in the executive body block,
  3. 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);
}

Recommended Today

Modify user information changeinfo

When judging the persistence layer: Problem: there is such a problem when modifying user information. For example: the user’s email is not required. It was not empty originally. At this time, the user deletes the mailbox information and submits it. At this time, if it is not empty to judge whether it needs to be […]