iOS中Block的循环引用问题
每周总结,第一周开始啦,最近在看AFNetworking源码时,看到了__strong的使用,很惭愧的说在平时开发中从来没有使用过__strong self ,除此之外,发现自己对Block的循环引用理解的也不深刻,今天就总结下block的循环引用问题
AFNetworking中__strongSelf应用如下
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
strongSelf.networkReachabilityStatus = status;
if (strongSelf.networkReachabilityStatusBlock) {
strongSelf.networkReachabilityStatusBlock(status);
}
};
本文将从以下几个方面介绍ARC下block的循环引用问题:
1. 什么是循环引用
2. 循环引用的结果
3. ARC下Block怎样产生的循环引用
4. 怎么样解决循环引用
1、什么是循环引用?
两个对象相互持有,导致两个对象都不能释放,造成内存泄漏。
2、如何产生了循环引用
观察以下代码存在些什么问题
@interface ViewController ()
@property (nonatomic, copy) void(^ testBlock)();
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.testBlock = ^(void){
[self doSomeThing];
};
}
-(void)doSomeThing{
NSLog(@"you are doing something");
}
@end
在上述代码中,XCode编译后提示[self doSomeThing],这一行可能会导致循环引用。
因为无论testBlock是copy还是strong属性,self都强引用了testBlock,在testBlock内部又调用了self,此时,testBlock强引用self(self的引用计数+1),导致ViewController实例无法被释放,因为自身的变量的引用计数永远大于1,循环引用。
为了解决这种问题,可以声明一个__weak变量指向self,在blcok中使用这个__weak变量,就不会导致self的引用计数+1,不会出现循环引用的问题了。
@interface ViewController ()
@property (nonatomic, copy) void(^ testBlock)();
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
__weak __typeof(self)weakSelf = self;
self.testBlock = ^(void){
[weakSelf doSomeThing];
};
}
-(void)doSomeThing{
NSLog(@"you are doing something");
}
@end
循环引用问题解决了,但是这时还有其他的问题,当你加了weakSelf后,Block中的self随时都会有被释放的可能,所以会出现一种情况,在异步调用的时候,执行到Block代码块时,self可能已经释放为nil了,所以为了避免这种情况发生,我们会重新strong self。一般情况下,我们都应该这么做,毕竟这么做是没什么风险,除非你不关心self在执行过程中变成nil,或者你确定它不会变成nil。
__weak __typeof(self)weakSelf = self;
self.testBlock = ^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf doSomeThing];
}];
weakSelf是为了block弱引用self,避免循环引用,而再声明一个strongSelf是因为一旦进入block执行,就不允许self在这个执行过程中释放。block执行完后这个strongSelf会自动释放,没有循环引用问题。
到此,有关本人对weakSelf的使用历程就介绍完毕啦,后续学习到新的知识,再更新,收车。