Block的循环引用

产生的原因是在 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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值