objective-c - ASIHTTPRequest block 内存泄漏

标签 objective-c ios cocoa-touch asihttprequest objective-c-blocks

我找不到这段代码中的错误:

-(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__]: message sent to deallocated instance 0xdeab380

我不知道如何保留请求数据而不泄漏内存。

最佳答案

我对这个库一无所知,所以你可能应该在这方面听取维京人的建议。

但是,我可以帮助您解决泄漏,这是在 block 和请求对象之间创建的保留循环的结果。具体来说,请注意您的 request 对象持有对代码块对象的强引用(通过 request.completionBlock)。

反过来,您的代码块对象持有对 request 的强引用,因为它访问 request.responseData。此外,请注意,您的代码看起来很可能是 ARC,但这并不能解释您的 _self 变量构造,它看起来像是非 ARC 弱引用。非 ARC __block 没有保留对象。在 ARC 下,__block 确实会导致保留。

假设使用 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];
}

现在,完成 block 持有对响应对象的弱引用,这打破了保留循环。请注意,一般来说,您应该创建对弱引用的本地强引用,以确保该对象停留足够长的时间来完成其工作。但是,在这种特定情况下,似乎没有必要。我认为没有图像是可以的。

关于objective-c - ASIHTTPRequest block 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12079251/

相关文章:

iphone - 如何以编程方式创建翻页效果?

Mono 中的 Objective-C

ios - avplayer item的重定向播放输出

objective-c - 对象通过测试 : Vs filteredSetUsingPredicate:?

ios - 下载和使用缓存图像时按顺序将图像加载到数组中

ios - 如何防止用户在 UITextfield - swift 中输入 '#' 和空格 (' ' )?

ios - 使用通知扩展会导致 Cocoapods 出现问题

ios - 当点击以编程方式创建的 UIButton 时,是否可以推送到可在界面生成器中编辑的 Controller ?

iphone - 在 UITableView 位置插入一行

ios - 重叠iOS组件viewController