Block循环引用的两种情况(self和私有成员变量)
2017-05-24 本文已影响31人
XDLee
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步。