简谈造成循环引用的原因以及处理办法
前段時間寫項目的時候我在每個block使用前我都加了一個__weak來修飾用@property描述的屬性,項目寫的差不多了回頭來反思,總覺得這種寫太麻煩了,回想起來,還是由于自己對于循環(huán)引用造成的原因理解不夠透徹,才導致做了很多的無用功。
廢話不多說,上代碼了 :
? ??/*
? ? // way 1? 獲取數(shù)據(jù)
? ? model = [[MoveModel alloc] init];
? ? model.successBlock = ^(id returnBlock) {
? ? ? ? NSArray *array = (NSArray *)returnBlock;
? ? ? ? _dataArray = array;
? ? ? ? [mainTableview reloadData];
? ? };
? ? [model getMoveData];
? ? */
?
? ??/*
? ? // way 2 獲取數(shù)據(jù)
? ? [MoveModel GetDataSuccessBlock:^(id returnValues) {
? ? ? ? NSArray *array = (NSArray *)returnValues;
? ? ? ? _dataArray = array;
? ? ? ? [mainTableview reloadData];
? ? }];
?? ? */
這兩種方式都是從別的類中獲取數(shù)據(jù)的方法,way1采用的是屬性block,way2采用的是參數(shù)block,而block內(nèi)部的數(shù)據(jù)處理方式是一樣的,但事實是way1造成了循環(huán)引用,而way2卻沒有。---不要問我怎么知道的,我就是知道~~
?
block在iOS開發(fā)中視為對象因此生命周期會一直等到持有者的生命周期結(jié)束了才會結(jié)束另外一方面
由于block的捕獲變量的機制使得block的對象也可能被block持有從而造成循環(huán)引用造成內(nèi)存泄露
?
第一種情況就是這樣的,block在控制器內(nèi)部實現(xiàn)的,它的持有者是控制器本身,而在block內(nèi)部又調(diào)用了_dataArray,它又持有了控制器。最終內(nèi)存泄露了。
?
解決辦法: 1:聲明?weakSelf
?
typeof(self) __weak weakSelf = self
?
block內(nèi)部的_dataArray 換成weakSelf.dataArray
?
但是這樣又會產(chǎn)生另外一種特殊情況,就是在回調(diào)block的時候,block中的對象很有可能已經(jīng)釋放了,找不到對象會導致crash。這種情況比較少見,但是需要防范。
?
2 在block內(nèi)部在聲明一個_strong 來修飾weakSelf 就行了。
?
下面是afnetworking中的源碼,既處理了循環(huán)引用的問題,又防范了突發(fā)情況的產(chǎn)生,處理方式值得借鑒:
__weak __typeof(self)weakSelf = self;
? ? AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
? ? ? ? __strong __typeof(weakSelf)strongSelf = weakSelf;
? ? ? ? strongSelf.networkReachabilityStatus = status;
? ? ? ? if (strongSelf.networkReachabilityStatusBlock) {
? ? ? ? ? ? strongSelf.networkReachabilityStatusBlock(status);
? ? ? ? }
? ? };
?
?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/110-913-1025/p/6993684.html
總結(jié)
以上是生活随笔為你收集整理的简谈造成循环引用的原因以及处理办法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机械师bios独立显卡怎么开启 如何开启
- 下一篇: hp笔记本怎么设置从u盘启动 HP笔记本