所谓闭环引用是2个货2个以上的相互关联的类的对象互相引用,形成了一种引用闭环问题,这种引用形成的问题是闭环内的全部对象都没法及时销毁,这种问题不是Objective-C和Swift所特有的,在常见的语言如Python,C/C++中均存在。html
(注:国内大多数程序员称为“循环引用”,单这种称呼很不恰当,闭环未必会循环,循环一样未必会闭环,只有闭环才是致使引用释放问题的关键,而不是循环)java
这里的闭环能够认为是一种死循环。程序员
使用代理和blocks时容易出现闭环引用async
以下,Page应该用了Book,Book引用了Page函数
OC中出现这种问题会致使dealloc不会被调用,在OC中解决此类问题,须要解除循环引用atom
咱们能够手动让咱们引用的对象变量赋值为nil(在合适的位置)spa
self.studentDelegate = nil;
固然,上面的代码须要【天时,地利,人和】,所以不适合通常性程序。3d
须要让Blocks变成弱引用(__weak或者__block)代理
让代理(委托)弱拷贝(weak)code
来段网上的代码
文/邻家菇凉(简书做者) 原文连接:http://www.jianshu.com/p/48b3d47fac12 著做权归做者全部,转载请联系做者得到受权,并标注“简书做者”。
主要代码以下
#import "NetworkTools.h" @interface NetworkTools () //用一个属性 来记录 函数传递过来的 block @property (nonatomic, copy) void(^finishedBlock)(NSString *); @end @implementation NetworkTools - (void)loadData:(void (^)(NSString *))finishedCallBack { //开始记录blcok self.finishedBlock = finishedCallBack; dispatch_async(dispatch_get_global_queue(0, 0), ^{ [NSThread sleepForTimeInterval:3]; //开始耗时任务 NSLog(@"开始加载数据"); dispatch_async(dispatch_get_main_queue(), ^{ //调用方法 [self working]; }); }); } - (void) working { //执行block if (self.finishedBlock) { self.finishedBlock(@"<html>"); } } - (void)dealloc { NSLog(@"Tools dealloc"); } @end
实现引用
#import "ViewController.h" #import "NetworkTools.h" @interface ViewController () ////解决方案切入点一,使用weak,防止 ViewController引用NetWorkTools成为强引用 @property (nonatomic, weak) NetworkTools *tools; @end@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.tools = [[NetworkTools alloc] init]; [self injectBlocksForNetWorkTools]; } //解决方案切入点二,使用 __weak - (void) injectBlocksForNetWorkTools{ __weak typeof(self) weakSelf = self; [self.tools loadData:^(NSString *html) { __strong typeof(self) strongSelf = weakSelf; NSLog(@"%@%@",html,strongSelf.view); strongSelf.view.backgroundColor = [UIColor redColor]; }]; } - (void)dealloc { NSLog(@"VC dealloc"); } @end
在这里说明一下__block和__weak的区别
所以,__block和__weak修饰符的区别实际上是挺明显的:
1.__block无论是ARC仍是MRC模式下均可以使用,能够修饰对象,还能够修饰基本数据类型。
2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。
3.__block对象能够在block中被从新赋值,__weak不能够。
代理必定要使用弱引用
Blocks可使用__weak或者__block可防止强引用
__block保证原有变量不被修改,__block对象在block中是能够被修改、从新赋值的,__weak容易释放,不能保证局部性,没有常量特征
__block对象在block中不会被block强引用一次,从而不会出现闭环引用问题。
Blocks属性尽可能使用weak修饰
只要保证引用闭环的其中一段弱引用就能够避免引用闭环