我无法在此代码中找到错误:
-(void)downloadImageFromURL:(NSURL*)url withCompletionBlock:(RSSMessageImageDownloadCompletionBlock)completionBlock
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
__block RSSMessage *_self = self;
request.completionBlock =
^{
__block NSData *responseData = request.responseData;
dispatch_async( dispatch_get_main_queue(), ^{
_self.image = responseData;
[[[UIApplication sharedApplication] delegate] saveContext];
if(completionBlock != nil)
{
completionBlock();
}
});
};
[request startAsynchronous];
}
在这种形式下,我的乐器有内存泄漏。我之所以认为是因为我之前缺少__block关键字:ASIHTTPRequest * request = [ASIHTTPRequest requestWithURL:url];
但是当我将这个关键字添加到上面的行时,我会收到如下错误:
* - [NSConcreteMutableData isNSData__]:发送到解除分配的实例0xdeab380的消息
我不知道如何保留请求数据而不是泄漏内存。
答案 0 :(得分:3)
我对这个图书馆一无所知,所以你应该注意维京人的建议。
但是,我可以帮助您解决泄漏问题,这是在块和请求对象之间创建的保留周期的结果。具体来说,请注意您的request
对象持有对代码块对象的强引用(通过request.completionBlock
)。
反过来,您的代码块对象保留了对request
的强引用,因为它访问request.responseData
。此外,请注意您的代码看起来很可能是ARC,但这并不能解释您的_self
变量构造,它看起来像非ARC弱引用。非ARC __block未保留该对象。在ARC下,__ lock确实会导致保留。
假设ARC,我建议进行以下更改。
-(void)downloadImageFromURL:(NSURL*)url withCompletionBlock (RSSMessageImageDownloadCompletionBlock)completionBlock
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
__weak ASIHTTPRequest *weakRequest = request;
__weak RSSMessage *weakSelf = self;
request.completionBlock = ^{
NSData *responseData = weakRequest.responseData;
// Check for nil if not ok with nil data
dispatch_async( dispatch_get_main_queue(), ^{
weakSelf.image = responseData;
[[[UIApplication sharedApplication] delegate] saveContext];
if(completionBlock != nil)
{
completionBlock();
}
});
};
[request startAsynchronous];
}
现在,完成块包含对响应对象的弱引用,这会破坏保留周期。请注意,通常,您应该创建对弱引用的本地强引用,以确保对象保持足够长的时间来完成其工作。但是,在这种特定情况下,似乎没有必要。我认为没有图像可以。
答案 1 :(得分:1)
- (IBAction)grabURLInBackground:(id)sender
{
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setCompletionBlock:^{
// Use when fetching text data
NSString *responseString = [request responseString];
// Use when fetching binary data
NSData *responseData = [request responseData];
}];
[request setFailedBlock:^{
NSError *error = [request error];
}];
[request startAsynchronous];
}
似乎请求本身需要标有__block
注意,original author of ASIHTTPRequest isnt supporting it anymore。他很好地解释了他的理由,并为替代项目提供了链接和建议。我对AFNetworking很满意,它有一个很好的基于块的界面。