Block循环引用问题(Objective-c)

造成循环引用的简单理解是:Block的拥有者在Block作用域内部又引用了自己,因此导致了Block的拥有者永远无法释放内存,就出现了循环引用的内存泄漏

示例代码

@interface ObjTest () {
    NSInteger testValue;
}
@property (copy, nonatomic) void (^block)();
@end

@implement ObjTest
- (void)function {
/*
    //这里会循环引用
    self.block = ^() {
        self.testValue = 100;
    };

*/

 __weak ObjTest* weakSelf = self;//使用弱引用,解决循环引用问题
    self.block = ^() {
        weakSelf.testValue = 100;
    };

}
@end

再看下面的例子

#import "networkTool.h"

@implementation networkTool

//定一个block的网络请求
-(void)loadData:(void (^)(NSString * _Nonnull))finishedBlock{
    //执行网络请求
    //...
    //完成回调返回
    finishedBlock(@"jsonData");
}

@end
@interface ViewController ()

@property (nonatomic,strong) networkTool *tool;

@end

@implementation ViewController

- (IBAction)button1Action:(id)sender {
    self.tool=[networkTool new];
    
    [self.tool loadData:^(NSString * _Nonnull jsonData) {
        NSLog(@"接收到请求数据:%@",jsonData);
        self.view.backgroundColor=[UIColor redColor];//此处没有循环引用
    }];
    
}

- (void)dealloc
{
    NSLog(@"ViewController -- dealloc");
}

@end

他们之间的引用关系 Block引用ViewController,ViewController引用networkTool,但是networkTool没有引用Block,如下图

 

下面这样会发生循环引用

@interface networkTool()
@property (nonatomic,copy) void(^finishedBlock2)(NSString*);
@end

@implementation networkTool

//定一个block的网络请求
-(void)loadData:(void (^)(NSString * _Nonnull))finishedBlock{
    self.finishedBlock2 = finishedBlock;//小心block循环引用
    //执行网络请求
    //...
    //完成回调返回
    finishedBlock(@"jsonData");
}

@end

//===============ViewController================

@interface ViewController ()
@property (nonatomic,strong) networkTool *tool;
@end

@implementation ViewController

- (IBAction)button1Action:(id)sender {
    self.tool=[networkTool new];
    
    //block引起循环引用问题
    [self.tool loadData:^(NSString * _Nonnull jsonData) {
        NSLog(@"接收到请求数据:%@",jsonData);
        self.view.backgroundColor=[UIColor redColor];
    }];
    
}

- (void)dealloc
{
    NSLog(@"ViewController -- dealloc");
}

@end

上面他们之间的引用关系 Block引用ViewController,ViewController引用networkTool,而且networkTool引用Block

解决方法:破坏这个闭合的环,如下

__weak typeof(self) weakSelf=self;
    [self.tool loadData:^(NSString * _Nonnull jsonData) {
        NSLog(@"接收到请求数据:%@",jsonData);
        weakSelf.view.backgroundColor=[UIColor redColor];
    }];

 

posted on 2019-07-10 10:13  二狗你变了  阅读(257)  评论(0编辑  收藏  举报

导航