zoukankan      html  css  js  c++  java
  • 由ASIHttpRequest里的block引发的思考

    项目发http请求,现在一般的都是用的第三方开源库,当然发异步请求时我们也会写几个回调函数来进行请求返回时的处理。不过前段时间看一个朋友写的代码,里面很用block简单的实现了回调相关的部分。比如:

    01 self.request=[ASIHTTPRequest requestWithURL:[NSURL URLWithString:url]];
    02 [_request setRequestMethod:@"GET"];
    03  
    04 [_request setCompletionBlock:^{
    05      
    06     _mobileField.enabled= YES;
    07     _nextStepBtn.enabled = YES;
    08     NSInteger statusCode = [_request responseStatusCode];
    09     NSString *result = [_request responseString];
    10 }];

    看后感觉非常的方便与简单,但是使用Instruments跑的时候老是有内存泄漏的问题。后来查找一翻,I find out the reason;
    原来block中调用了self或者self的成员变量,block就retain了self,而self也retain block,所以self和block都无法释放,最终形成cycle。
    正确的写法如下:

    01     self.request=[ASIHTTPRequest requestWithURL:[NSURL URLWithString:url]];
    02     [_request setRequestMethod:@"GET"];
    03     __unsafe_unretained ASIHTTPRequest *_requestCopy = _request;
    04     __unsafe_unretained RegistUserViewController *this = self;
    05     [_request setCompletionBlock:^{
    06          
    07         this.mobileField.enabled= YES;
    08         this.nextStepBtn.enabled = YES;
    09         NSInteger statusCode = [_requestCopy responseStatusCode];
    10         NSString *result = [_requestCopy responseString];
    11 }];

    注意其中的__unsafe_unretained关键词,这个就是让block对所修饰的变量使用弱引用,也就ARC中的__weak。这样修饰的变量就不会被retain。

    还有一种是用__block关键词的写法,也是官方文档中的写法(http://allseeing-i.com/ASIHTTPRequest/How-to-use);

    01 - (IBAction)grabURLInBackground:(id)sender
    02 {
    03    NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
    04    __block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    05    [request setCompletionBlock:^{
    06       // Use when fetching text data
    07       NSString *responseString = [request responseString];
    08   
    09       // Use when fetching binary data
    10       NSData *responseData = [request responseData];
    11    }];
    12    [request setFailedBlock:^{
    13       NSError *error = [request error];
    14    }];
    15    [request startAsynchronous];
    16 }

    还有一种将self改成弱引用的写法是
    __block typeof(self) bself = self;

    关于block中的成员变量的调用方法也要注意下面两点:
    对于property就用点操作符 bself.xxx
    对于非property的成员变量就用->操作符 bself->xxx

    最后总结,所有的这些都是围绕一点,block会retain相应的变量,我们要使用用弱引用修饰的变量

  • 相关阅读:
    【C++ OpenGL ES 2.0编程笔记】8: 使用VBO和IBO绘制立方体 【转】
    顶点缓存对象(VBO)【转】
    CompileGLShader
    VR虚拟现实的工作原理,你知道多少?【转】
    VR/AR工作原理、目前存在的技术问题
    Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'
    nginx配置用户认证
    恢复阿里云RDS云数据库MySQL的备份文件到自建数据库
    阿里云rds linux平台使用wget 工具下载备份与日志文件
    screen 命令使用及示例
  • 原文地址:https://www.cnblogs.com/lisa090818/p/3171793.html
Copyright © 2011-2022 走看看