所謂閉環引用是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修飾
只要保證引用閉環的其中一段弱引用就能夠避免引用閉環