Block循环引用的两种情况(self和私有成员变量)

Block的循环引用问题非常常见

1、Block 内部引用 self,造成循环引用

(1)这种 Block 循环引用最为常见,以下代码中的 self(控制器)无法释放

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) void(^demoBlock)();

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
   
    [self blockDemo1];
}

#pragma mark - block 内部使用 self, 造成的循环引用
- (void)blockDemo1 {
    
    self.demoBlock = ^{
        self.name = @"Jack";
    };
}

- (void)dealloc {
    NSLog(@"%s", __FUNCTION__);
}

(2)解决办法

1> 在 Block 外部加上 __weak typeof (self) weakSelf = self; 
2> 在 Block 里面使用 weakSelf.属性 就ok了。
只需做到这两步就可以解决循环引用。

(3)代码如下

#pragma mark - block 内部使用 self, 造成的循环引用
- (void)blockDemo1 {
    
    __weak typeof(self) weakSelf = self;
    self.demoBlock = ^{
        weakSelf.name = @"Jack";
    };
}

2、Block 内部引用私有成员变量,造成的循环引用

(1)_成员变量 默认是 __strong 修饰的,Block内部直接引用 _成员变量,就会造成循环引用

#import "ViewController.h"

@interface ViewController () {
    NSMutableArray *_nameList;
}

@property (nonatomic, copy) void(^demoBlock)();

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
   
    [self blockDemo2];
}

#pragma mark - block 内部使用私有成员变量,造成的循环引用
- (void)blockDemo2 {
   
    self.demoBlock = ^ {
        [_nameList addObject:@"Jack"];
    };
}

- (void)dealloc {
    NSLog(@"%s", __FUNCTION__);
}

(2)解决办法

1> 在 Block 外部加上 __weak typeof (self) weakSelf = self; 
2> 在 Block 内部必须加上 __strong typeof(weakSelf) strongSelf = weakSelf;
3> 最后,使用 strongSelf->_成员变量 来处理。
注意: 第2步不能少。

(3)代码如下

- (void)blockDemo2 {
    
    __weak typeof(self) weakSelf = self;
    self.demoBlock = ^ {
        __strong typeof(weakSelf) strongSelf = weakSelf;
        [strongSelf->_nameList addObject:@"Jack"];
    };
}

如果没有第2步,就会报以下错误

错误信息.png

因此,必须加上第2步。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容