这篇博文继续block的常见错误——循环引用。
循环引用是很多初学者不能察觉的,其产生的原因,是block中的代码会对对象进行强引用。
读者请阅读示例代码1,并思考示例代码1所创建的对象能否被正常销毁?
示例代码1:
//DemoObj.m @interface DemoObj ()
@property (nonatomic, strong) NSMutableArray *myBlocks;
@end #pragma mark 将代码改为调用self的方法 -(NSMutableArray *)myBlocks
{
if (_myBlocks == nil) {
_myBlocks = [NSMutableArray array];
} return _myBlocks;
} - (instancetype)init
{
self = [super init];
if (self) {
int(^sum)(int, int) = ^(int x, int y) {
return [self sum:x y:y];
};
[self.myBlocks addObject:sum];
} return self;
} -(int)sum:(int) x y:(int)y
{
return x + y;
} #pragma mark 对象被释放时自动调用
- (void)dealloc
{
NSLog(@"DemoObj被释放");
}
答案是不能正常释放的。读者不妨在xcode中试试。
产生原因在block代码中出现了self:
int(^sum)(int, int) = ^(int x, int y) {
return [self sum:x y:y];
};
此时sum的block对self强引用,在加上self对myBlocks强引用:
@property (nonatomic, strong) NSMutableArray *myBlocks;
以及sum block被添加到数组时,会被数组强引用:
[self.myBlocks addObject:sum];
这三个引用之间形成了循环引用,如下图:
循环引用的结果就是对象无法被释放!
碰到这类问题,程序员如何解除循环引用呢?
有以下几种解决方案:
1.在block代码中不要引用self以及其他局部变量;如
int(^sum)(int, int) = ^(int x, int y) {
return [self sum:x y:y];
};
修改成
int(^sum)(int, int) = ^(int x, int y) {
return x + y;
};
2.使用__weak关键字,可以将局部变量声明为弱引用
如:
- (instancetype)init
{
self = [super init];
if (self) {
int(^sum)(int, int) = ^(int x, int y) {
return [self sum:x y:y];
};
[self.myBlocks addObject:sum];
} return self;
}
修改为:
- (instancetype)init
{
self = [super init];
if (self) {
__weak DemoObj *weakSelf = self;
int(^sum)(int, int) = ^(int x, int y) {
return [weakSelf sum:x y:y];
};
[self.myBlocks addObject:sum];
} return self;
}
block的循环引用就说到这,下一篇继续来讲解block的常见错误