block循环引用会导致开辟的内存空间因为相互的引用而无法释放,是占用多余的内存空间的行为。在开发中,我们或多或少的都会遇到block块,但是新手因为接触的少,无法有条理的进行分析来确认是否存在循环引用,下面通过一个简单的代码事例来讲解下block的循环引用以及weak self的使用条件。
首先我先创建了一个Person类,设置其属性并导入ViewController控制器中:
我们先来看会导致循环引用的情况:
#import "ViewController.h"
#import "Person.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Person *somebody = [[Person alloc] init];
somebody.name = @"某人";
somebody.block = ^{
NSLog(@"%@",somebody.name);
};
somebody.block();
}
@end
解析:通过Person类创建的somebody对象,有个强指针指向着block,block指向着ViewController控制器中的blcok代码块,在ViewController控制器中的block代码块中因为需要打印somebody的名字,所以需要使用到somebody,就使得block代码块有一个强指针指向了somebody,造成了循环引用,因为无法断开其中的任何一条指向,致使它们无法得到释放。图解:
既然我们清楚了循环引用,我们就来断开这样的循环引用,代码调整如下:
#import "ViewController.h"
#import "Person.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Person *somebody = [[Person alloc] init];
somebody.name = @"某人";
//通过block代码块外部声明一个弱引用,让block代码块内部产生一个弱引用指向somebody对象,解除循环引用
__weak typeof(somebody) weakSomebody = somebody;
somebody.block = ^{
NSLog(@"%@",weakSomebody.name);
};
somebody.block();
}
@end
解析:我们通过__weak typeof(somebody) weakSomebody = somebody;将block代码块中对somebody的强引用转化成了弱引用,当代码执行完毕,block对象会被释放,内存引用关系得到解除。图解:
现在我们应该也明白就是在造成循环的时候,才需要用到__weak,在没有造成循环引用的情况下,我们还是可以在block代码块中使用对象本身的。
但是如果在blcok代码块中存在异步执行或延迟操作的话,__weak的对象很有可能会提前释放,让我们无法完成我们的需求,这种情况下也是不能够使用__weak的,这种情况的解决办法下篇博客进行讲解。