内存泄漏从服务器下载图像

时间:2013-03-05 19:11:21

标签: ios image memory memory-leaks

我有一个分页滑块视图,每页都有一个图像。我正在使用NSOperationQueue帮助我在程序运行时从服务器下载图像。 NSOperationQueue用于调用以下方法,

-(NSData *)imageWith:(NSString *)imageName
{

NSString *imagePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:imageName];
NSData *imageData = [NSData dataWithContentsOfFile:imagePath];

if (!imageData) {

   imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[[NSString stringWithFormat:@"%@/%@", picsURL,imageName] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]]];

    if (imageData) {

        [imageData writeToFile:imagePath atomically:YES];
    }
}     
 return imageData;
}

然后我使用主线程在scrollerview上显示下载的图像:

[self performSelectorOnMainThread:@selector(loadPic:) withObject:[NSArray arrayWithObjects:[self imageWith:[picsNames objectAtIndex:imageView.tag]], [NSString stringWithFormat:@"%d", imageView.tag], nil] waitUntilDone:YES];

调用以下方法:

-(void)loadPic:(NSArray *)imageAndTagArray
{
    if (imageAndTagArray.count) {

    //loading the image to imageview
    UIImageView *imageView = (UIImageView *)[scrollView viewWithTag:[[imageAndTagArray objectAtIndex:1] intValue]];
    imageView.image = [UIImage imageWithData:((NSData *)[imageAndTagArray objectAtIndex:0])];

    //stopping the indicator
    [((UIActivityIndicatorView *)[imageView viewWithTag:ACTIVITY_INDICATOR_TAG]) stopAnimating];
}
}

前60张图片的一切正常,但之后我收到了内存警告,大约100张图片后应用程序崩溃了。

我花了这么多时间在这上面,我无法弄清楚该怎么做。我使用过仪器并没有检测到任何泄漏。我也使用了Analyze,它确实显示了任何东西。

编辑:

如果我用以下定义替换imageWith:方法定义,我仍然会收到警告,其中5.jpg是本地图像。

-(NSData *)imageWith:(NSString *)imageName
{
     return UIImagePNGRepresentation([UIImage imageNamed:@"5.jpg"]);
}

让我告诉你更多有关情况的信息。

当应用程序启动时,我有一个带有分页滚动视图的视图,其中每页包含9个图像。 scrollview使用nsoperationqueue加载调用imageWith:方法的图像。

当用户点击任何图像时,将打开第二个视图,并显示所选图像的完整显示。此第二个视图还有一个滚动视图,其中包含与第一个视图相同的图像,但具有完整显示,即每页1个图像。

当您在第二个视图上并来回滚动时,应用程序在加载约60张图像后崩溃。 如果说它加载50张图像然后点击后退按钮并转到第一个视图然后点击另一个图像并转到第二个视图并加载大约10个图像,它也会崩溃。

1 个答案:

答案 0 :(得分:1)

听起来你在内存中藏有太多图像。当您打开第二个视图时,它会再次从磁盘重新加载图像,直到您最终获得所有图像的两个副本。

UIImage类可以帮助您进行内存管理。在其reference page中,它提到它能够在低内存情况下清除其数据,然后在需要再次绘制时从磁盘重新加载该文件。这可能是您的解决方案。

但是,当您从磁盘读取NSData创建映像时,UIImage可能无法清除其内存 - 它不会知道您的映像只是存储在磁盘上,所以它可以'扔掉数据并稍后重新加载。

尝试更改“imageWith”方法,以便在返回之前从磁盘上的文件URL创建UIImage(通过imageWithContentsOfFile),并返回UIImage而不是返回中间NSData。这样,UIImage将知道其映像源来自磁盘的位置,并能够在内存受限于设备时智能地清除/重新加载它。