zoukankan      html  css  js  c++  java
  • 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];
        }];
  • 相关阅读:
    ehcache如何判断缓存数据是否存在--isKeyInCache
    ehcache 缓存监控
    XSS跨站脚本攻击
    java根据文件头判断文件类型
    Spring Security使用Authentication获取当前用户信息
    HttpSessionListener的用法
    ehcache缓存配置与参数说明
    [CERC2017]Buffalo Barricades
    [POI2001]Gra绿色游戏
    移动游戏By HYJ
  • 原文地址:https://www.cnblogs.com/dhui69/p/11162125.html
Copyright © 2011-2022 走看看