使用块时的内存增长& Path的FastImageCache

时间:2014-03-17 19:19:47

标签: ios objective-c automatic-ref-counting objective-c-blocks nsurlcache

我正在使用Path的优秀FastImageCache库,并且遇到了保留问题。

具体来说,当尝试将UIImages(从服务器下载)提供给图像缓存时。当交给完成块时,图像似乎仍然保留。 ARC没有发布是。

当处理大量大图像时,这会导致显着的内存增长。

- (void)imageCache:(FICImageCache *)imageCache wantsSourceImageForEntity:(id<FICEntity>)entity withFormatName:(NSString*)formatName completionBlock:(FICImageRequestCompletionBlock)completionBlock
{
    ...
    NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest
                                              returningResponse:&response
                                                          error:&error];
    UIImage* image = [[UIImage alloc] initWithData:data];
    completionBlock(image); // <-----
    ...
}

我确认没有用图像调用完成块,不会导致内存增长。

另外,不使用绘图块本身的图像,也可以避免内存增长。所以我认为这确实与保留的图像有关。

- (FICEntityImageDrawingBlock)drawingBlockForImage:(UIImage*)image withFormatName:(NSString*)formatName
{
    FICEntityImageDrawingBlock drawingBlock = ^(CGContextRef contextRef, CGSize contextSize) {
        CGRect contextBounds = CGRectZero;
        contextBounds.size = contextSize;
        CGContextClearRect(contextRef, contextBounds);
        CGContextSetInterpolationQuality(contextRef, kCGInterpolationMedium);
        UIGraphicsPushContext(contextRef);
        [image drawInRect:contextBounds]; // <---- 
        UIGraphicsPopContext();
    };

    return drawingBlock;
}

如何避免保留图像或如何强制它被释放?我尝试将其设置为nil并添加@autoreleasepool,但这并没有帮助。

@autoreleasepool {
        NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest
                                              returningResponse:&response
                                                          error:&error];

        UIImage* image = [[UIImage alloc] initWithData:data];
        completionBlock(image);
        image = nil;
        data = nil;

        [[NSURLCache sharedURLCache] removeAllCachedResponses];
    }

感谢您的帮助。

更新2014年3月18日
注意:这似乎不是模拟器中的问题,只是在设备上。

3 个答案:

答案 0 :(得分:0)

我不确定您的图片是否泄漏 - 我认为这可能是传递到您的绘图块中的上下文。在你完成使用之后,你能断言你是在释放它吗?

答案 1 :(得分:0)

所以我也开始在这里泄漏,很可能是从一些微妙的保留周期,但无论出于何种原因,当我从imageWithContentsOfFile切换到initWithData时,我的问题就消失了。我没有花时间调查原因,但我确信使用[[UIImage alloc] initWithData:data];会阻止此uiimage被释放。我认为这是有道理的,特别是如果你在一个块内执行此操作,分配可能导致我们的引用计数变为+1,然后是块强引用创建循环限制。

进行此更改后,我使用Instruments检查了一下,我的堆不再是膨胀。我很容易找到这个因为我也有非常大的图像所以我的生活内存使用会立即飙升并很快崩溃。

答案 2 :(得分:0)

感谢@Ryan Romanchuk的评论。我尝试了你提到的方法(从initWithData更改为imageWithContentsOfFile)。我检查了作者的代码,发现他还使用了imageWithContentsOfFile(我的是imageWithCGImage)。这个对我有用。这就是我所做的:将照片保存为jpeg文件,使用imageWithContentsOfFile加载图像。最后,内存分配急剧下降。 但是,我仍然可以观察到轻微的分配增长。看看我的截图:

1)我做了几代观察公羊的成长。有一些增长大约1M。 enter image description here

2)我深入挖掘了一代,发现增长与saveMetadata有关。 enter image description here

3)位于NSDictionary * metadataDictionary = [NSDictionary dictionaryWithObjectsAndKeys:                                         [_indexMap copy],FICImageTableIndexMapKey,                                         [_sourceImageMap copy],FICImageTableContextMapKey,                                         [[_MRUEntries array] copy],FICImageTableMRUArrayKey,                                         [_imageFormatDictionary copy],FICImageTableFormatKey,nil]; enter image description here enter image description here