• 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];
        }];
  • 相关阅读:
    删除表空间 数据库备份 创建用户
    javax.persistence包
    JNDI
    J2EE中关于session 的生命周期
    多表关联
    归档程序错误。在释放之前仅限于内部连接
    spring集成jpa
    Tree.Panel各项属性
    eclipse调试以及step into step over step return区别
    wininet.dll函数库:不会过期的cookie
  • 原文地址:https://www.cnblogs.com/dhui69/p/11162125.html
Copyright © 2020-2023  润新知