何为循环引用?
简单理解:对象A强引用B,对象B也强引用A;
![](https://img.haomeiwen.com/i648983/d8db223eff2f6811.png)
何时会发生循环引用?
使用delegate、block的时候
Example:
新建一个Friend类如下:
#import <Foundation/Foundation.h>
typedef void(^FriendBLK)(NSString *name);
@interface Friend : NSObject
@property (nonatomic, strong) NSArray *arr;
@property (nonatomic, copy) FriendBLK block;
@end
#import"Friend.h"
@implementationFriend
- (id)init
{
if(self= [superinit]) {
self.arr=@[@111,@222,@333];
self.block= ^(NSString*name){
NSLog(@"name :%@ , block arr:%@", name, name);
};
}
returnself;
}
- (void)dealloc{
NSLog(@"Friend dealloc");
}
@end
然后使用的地方调用下:
Friend*f = [[Friendalloc]init];
f.block(@"yk-test");
当f所在的runloop结束时,会发现控制台打印
2016-09-07 10:20:15.264 RACDemo[2459:23583] name :yk-test , block arr:yk-test
2016-09-07 10:20:15.264 RACDemo[2459:23583] Friend dealloc
这表明f对象被释放了,不存在内存泄漏。然后我们稍微修改下代码:
![](https://img.haomeiwen.com/i648983/de589bcc00a77dc9.png)
�再次运行下,发现只会打印
2016-09-07 10:27:24.216 RACDemo[2510:28277] name :yk-test , block arr:(
111,
222,
333
)
并不会调用dellaoc释放self 也就是f对象未被释放,即存在内存泄漏;为了更好理解引用循环问题,我们添加一个延迟队列,代码如下:
![](https://img.haomeiwen.com/i648983/3999939bd828c60f.png)
然后发现f对象也是不释放的,下面来分析原理:
![](https://img.haomeiwen.com/i648983/a324a188f16b461f.png)
外面f.block(@"yk-test");结束后,需要释放f对象,通知即将释放,但是这时候block内部还在强引用自己的arr�数组。�Runloop发现f的retain count不为0,于是乎f就不能释放。等到block里面的引用self释放之后,也就是retain count为0时,才能正在释放;
解决方案:弱引用
__weak__typeof(self)wself =self; 或者使用@weakify() @strongify()
原理示意图:
![](https://img.haomeiwen.com/i648983/ab7f4ae97a0d7e0f.png)
基本Block的问题解决了。其实我们在使用delegate的时候也会出现同样的问题,所以使用delegate都用weak,而不能用strong;
![](https://img.haomeiwen.com/i648983/98498b10024db3c6.png)
以上就是日常开发的内存泄漏之循环引用了,有不对的地方请留言;
网友评论