1

我有一个分页滑块视图,每页上都有一个图像。我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;
}

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

[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 张图片后应用程序崩溃。

我在这方面花了很多时间,但我不知道该怎么做。我用过 Instruments,它没有检测到任何泄漏。我也使用了分析,这也显示了任何东西。

编辑:

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

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

让我告诉你更多的情况。

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

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

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

4

1 回答 1

1

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

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

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

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

于 2013-03-05T22:57:31.777 回答