iOS 循環(huán)引用

產(chǎn)生原因: 兩個強引用對象互相指向對方
強引用對象互相指向時,雙方的引用計數(shù)都+1,導致任何時候引用計數(shù)都不為0,始終無法釋放,無法釋放他們的內(nèi)存,即使已經(jīng)沒有變量持有他們
危害: 使內(nèi)存消耗過高,性能變差,app閃退等.
具體情況:

  1. 父類與子類
    例如在使用UITableView時,傳一個Controller給cell使用,自定義 cell: TestTableViewCell,在cell里聲明一個UITableView的變量,在cellForRowAtIndexPath里將tableView傳入cell.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexpath{
  TestTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellIdentifier" forIndexPath:indexPath];
  cell.tableView = tableView;
  return cell;
}

在聲明tableView時,如果我們用strong來修飾的話就會造成循環(huán)引用

@interface TestTableViewCell: UITableViewCell
@property (nonatomic, weak) UITableView  *tableView;
@end

2.Block

@property (nonatomic, copy) TestBlock completionHandler;
self.completionHandler = ^{
  [self.property removeObserver: self forKeyPath: @"pathName"];
  // self do something
}

block在copy時都會對block內(nèi)部用到的對象進行強引用,該類又將block作為自己屬性變量,block的方法體里又使用了該類,形成了環(huán)狀,造成了循環(huán)引用.
避免:

__weak typeof(self) weakself = self;
self.completionHandler = ^{
  //和block外的self,指向一樣,但是是不同的變量
  __strong typeof (weakself) strongSelf = weak self;
  [strongSelf doSomething];
}

先將強引用的對象轉為弱引用指針,防止了block和對象之間循環(huán)引用,再在block里將弱指針轉化為強引用指針,防止了多線程和ARC環(huán)境下弱引用隨時被釋放的問題.

或者 改為Block傳參:

self.blk = ^ (UIViewController *vc){
  NSLog(@"use property: %@", vc.name);
};
self.blk(self);
  1. Delegate:
    我們在聲明代理時,會寫
@property (nonatomic, weak) id <TestDelegate> delegate;

如果我們不使用weak,而是使用了strong,那么兩個類之間的代理就會變成:

aViewController.delegate = self; //假設self為aViewController, a和delegate的引用計數(shù)均加1,a與delegate相互強指向,造成循環(huán)引用.

4.NSTimer
ViewController --強引用--> 屬性Timer --強引用--> Target(self = ViewController) --強引用--> ViewController

比如在ViewController B 中有一個Timer

@property (nonatomic, strong) NSTimer *timer;

創(chuàng)建并掛載到main runloop

self.timer = [NSTimer scheduledTimerWithTimerInterval: 1 target: self selector:@selector(timerAction:) userInfo:nil repeats: true];

然后退出Controller B的時候忘記關掉timer, Controller B將不會釋放, B與timer循環(huán)引用,因為創(chuàng)建timer時指向了self
避免:
在適當?shù)那闆r下,invalidate timer,因為timer在validate狀態(tài)下引用計數(shù)始終大于0
注意:在上面的方法中,repeats參數(shù)為YSE時,NSTimer會保留目標對象,等到自身失效才釋放.執(zhí)行完畢任務后,一次性的定時器會自動失效,重復性的定時器,需要手動調用invalidate方法才會失效

若單純的想在 Controller B 的dealloc方法中去釋放timer是不可能調用的,因為timer沒有釋放的話,controller B也是不能釋放的,dealloc方法不會被調用

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 介紹: 在Objective-C的開發(fā)中循環(huán)引用(retain cycle)是指兩個(或多個)對象之間產(chǎn)生了互相強...
    nero_i閱讀 810評論 0 3
  • 原文地址:http://www.cnblogs.com/wengzilin/p/4347974.htmlARC已經(jīng)...
    Code丶Ling閱讀 1,517評論 5 8
  • 循環(huán)引用,故名思義,即強引用的引用鏈上出現(xiàn)了環(huán)。A、B兩個對象,A強引用了B,B又強引用了A,導致在任何時候A、B...
    Shaw1211閱讀 803評論 0 48
  • 參考文章:http://www.itdecent.cn/p/a51c6dd12587http://www.jian...
    peaktan閱讀 6,379評論 0 18
  • 總結梳理一下循環(huán)引用相關的知識點。 循環(huán)引用分三種:1.自循環(huán)引用,2.相互循環(huán)引用,3.多循環(huán)引用,這三種就不多...
    Horson19閱讀 785評論 0 2

友情鏈接更多精彩內(nèi)容