IOS 常見循環(huán)引用問題

問題出現(xiàn)描述
當多個對象相互持有形成一個封閉的環(huán)時,循環(huán)引用問題隨之出現(xiàn),導(dǎo)致內(nèi)存泄漏。

常見幾種循環(huán)引用總結(jié)
1、代理delegate 使用關(guān)鍵字 strong 描述

  @property(nonatomic,strong)delegate;

  self.operationView.delegate = self;

在這里 B強引用A,而A的delegate屬性指向B,這里的delegate是用strong修飾的,所以A也會強引用B,這是一個典型的循環(huán)引用樣例。其解決其的方式大家也都知道,即將delegate改為弱引用(weak)。

2、block與環(huán)

self.block = ^{
      self.count =2; 
 };

在這里 self持有block,而堆上的block又會持有self,所以會導(dǎo)致循環(huán)引用,解決這種循環(huán)引用的常用方式如下(這種解決方式可以解決大部分block引起的循環(huán)引用):

__weak typeof(self) weakSelf = self;

self.block = ^{
      weakSelf.count =2; 
 };

特備注:有時候直接使用 weakSelf 會導(dǎo)致內(nèi)存提前回收,導(dǎo)致出現(xiàn)錯誤,如下:

  @interface UIviewController ()
  @property (nonatomic, copy) dispatch_block_t block;
  @property (nonatomic, strong) NSString *str;
  @end
 @implementation UIviewController 
 - (void)dealloc {
}
- (void)viewDidLoad {
[super viewDidLoad];
self.str = @"111";
__weak typeof(self) weakSelf = self;
self.block = ^{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"%@", strongSelf.str);
    });
};
self.block();   

}

這里會有兩種情況:
從 一個VC push到 上面的VC,10s之內(nèi)沒有pop的話,block會執(zhí)行打印出來111。
從一個VC push到 上面的VC,10s之內(nèi)pop的話 ,上面的VC會立即執(zhí)行dealloc,從而導(dǎo)致block打印出(null)。這種情況就是使用weakSelf的缺陷,可能會導(dǎo)致內(nèi)存提前回收。
解決辦法:

  @interface UIviewController ()
  @property (nonatomic, copy) dispatch_block_t block;
  @property (nonatomic, strong) NSString *str;
  @end
 @implementation UIviewController 
 - (void)dealloc {
}
- (void)viewDidLoad {
[super viewDidLoad];
self.str = @"111";
__weak typeof(self) weakSelf = self;
self.block = ^{
  __strong typeof(self) strongSelf = weakSelf;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"%@", strongSelf.str);
    });
};
self.block();   

}
這么做和直接用self有什么區(qū)別,為什么不會有循環(huán)引用:外部的weakSelf是為了打破環(huán),從而使得沒有循環(huán)引用,而內(nèi)部的strongSelf僅僅是個局部變量,存在棧中,會在block執(zhí)行結(jié)束后回收,不會再造成循環(huán)引用。
這么做和使用weakSelf有什么區(qū)別:唯一的區(qū)別就是多了一個strongSelf,而這里的strongSelf會使ClassB的對象引用計數(shù)+1,使得ClassB pop到A的時候,并不會執(zhí)行dealloc,因為引用計數(shù)還不為0,strongSelf仍持有ClassB,而在block執(zhí)行完,局部的strongSelf才會回收,此時ClassB dealloc。

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

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

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