您的位置:首页 > 其它

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: