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相应的变量,我们要使用用弱引用修饰的变量

  • 相关阅读:
    殷浩详解DDD:如何避免写流水账代码?
    如何从 0 到 1 开发 PyFlink API 作业
    探秘RocketMQ源码——Series1:Producer视角看事务消息
    教父郭盛华透露:PHP编程语言中多个代码执行缺陷
    互联网用户仍然容易受到黑客社会工程学攻击
    揭秘郭盛华在世界的排名,才华与颜值并存的男神
    什么是逆向工程?黑客是如何构建可利用的漏洞?
    人工智能时代,计算机网络主要面临哪些安全威胁?
    【2020-10-01】国庆堵车不堵心
    【2020-09-30】走起来慢,但实际很快
  • 原文地址:https://www.cnblogs.com/lisa090818/p/3171793.html
Copyright © 2011-2022 走看看