Block的循环引用
2015-12-11 23:13
405 查看
产生的原因是在 block中使用self ,此时 block由于 copy的原因,对 self 是强引用,并且将 block作为 self 的成员变量的闭包,而且 self 的改成员变量中又对 block 闭包强引用,所以该成员变量间接地对 self也是强引用,而 self 对于成员变量的强引用,造成了循环引用.二者不能都释放,会造成内存泄露
例子:
例子:
//创建 NetworkTools #import "NetworkTools.h" @interface NetworkTools () @property (nonatomic, copy) void (^finishedBlock)(NSString *); @end @implementation NetworkTools //block是一组准备好的代码 在需要的时候执行 //可以当做参数传递 //在异步方法中如果能直接执行block就直接执行 //如果不需要立即执行 就需要用一个属性来 记录block 在需要的时候执行 //finished执行完就解除了对self的强引用 - (void)loadData:(void (^)(NSString *))finished { //记录block self.finishedBlock = finished; //异步加载数据 dispatch_async(dispatch_get_global_queue(0, 0), ^{ //睡 3秒 [NSThread sleepForTimeInterval:3]; //耗时任务结束后 主线程完成回调 dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"回调数据"); // finished(@"终于拿到数据"); [self working]; }); }); } - (void) working { //在调用block的时候需要判断是否为空 if (self.finishedBlock) { self.finishedBlock(@"回调数据"); } } - (void)dealloc{ NSLog(@" tools 88"); } @end
//实例化 NetWorking,并且添加数据 #import "ViewController.h" #import "NetworkTools.h" /* 接触循环引用 打破引用循环即可 1.不使用成员变量 来调用闭包 2.__weak or __unsafe_unretained */ @interface ViewController () @property (nonatomic, strong) NetworkTools *tools; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //加载网络数据 self.tools = [[NetworkTools alloc] init]; //以后工作中 大家会看到大量以下代码 //不会有任何不同 //将一个弱引用的对象 在闭包中变成强引用的对象 希望 在对象self在被回收时 记录self 以便能够继续访问方法 //但是就是个棒槌 没有任何作用 __unsafe_unretained typeof(self) weakSelf = self; [self.tools loadData:^(NSString *html) { __strong typeof(self) strongSelf = weakSelf; NSLog(@"data = %@",html); NSLog(@"%@",strongSelf.view); }]; } - (void) method2 { //加载网络数据 self.tools = [[NetworkTools alloc] init]; //定义block的时候 在block中使用了外部变量 会默认做copy操作 //会对self进行强引用 ////接触循环引用的方法二 // __weak 相当于 weak关键字修饰 当对象被回收时 对象地址会自动指向nil 给nil发送消息 在OC中是可以的 //不会造成野指针访问 //iOS 5.0之后推出的 __weak typeof(self) weakSelf = self; // __unsafe_unretained typeof(self) weakSelf = self; [self.tools loadData:^(NSString *html) { NSLog(@"data = %@",html); //现在会产生循环引用嘛? NSLog(@"%@",weakSelf.view); }]; } - (void) method1 { //加载网络数据 self.tools = [[NetworkTools alloc] init]; //定义block的时候 在block中使用了外部变量 会默认做copy操作 //会对self进行强引用 // __weak typeof(self) weakSelf = self; //接触循环引用的方法1 //__unsafe_unretained 相当于assgin关键字 修饰 当对象被回收是 对象地址不会指向nil //iOS 4.0推出的 //会导致坏地址访问 俗称 野指针 __unsafe_unretained typeof(self) weakSelf = self; [self.tools loadData:^(NSString *html) { NSLog(@"data = %@",html); //现在会产生循环引用嘛? NSLog(@"%@",weakSelf.view); }]; } - (void)dealloc{ NSLog(@" VC 88"); } @end
相关文章推荐
- Android
- Subsets -------bit
- Codeforces Round #334 (Div. 2) D. Moodular Arithmetic
- LeetCode 刷题: 删除已排序链表中的重复节点
- JFinal开发Demo
- LeetCode 237:Delete Node in a Linked List
- 工作常用英语单词整理1
- ubuntu安装mysql可以启动,但找不到mysql.sock
- 死锁-猩猩过谷
- python 版本控制及django,git的使用
- 研究生生活规划
- mssql server 安装问题处理
- Unable to start gdbserver on port '63411' Can't open socket: Permission denied.的解决办法
- BZOJ 1452: [JSOI2009]Count 二维树状数组
- 初识Jsoup之解析HTML
- linux中断驱动程序
- 递推专题 - 两种状态互推问题:经典问题 打砖块 + NOIP2015 Day2 T2
- 接口和抽象类有什么区别
- 第二次作业
- Hadoop2.5.2源码编译及导入Eclipse