【问题标题】:Memory issue when using large NSArray of UIImage使用 UIImage 的大 NSArray 时的内存问题
【发布时间】:2013-04-17 02:26:53
【问题描述】:

我正在尝试使用 UIImages 数组在屏幕上显示大量图像。目前我将每个图像添加到 NSMutableArray 中,然后在需要时访问它们,但是随着图像数量的增加,应用程序最终会崩溃。

我尝试使用 Instruments 来计算内存分配,但似乎一旦内存达到 20MB 左右,应用程序就会崩溃。有没有办法解决这个问题?或者当我这样做时有什么方法可以尽可能地节省内存?即使您对此没有答案,有没有人遇到过类似的问题?如果是这样,您是如何妥协/解决的?

顺便说一句,我没有想到存储到文件(或核心数据)和从文件(或核心数据)中检索的选项,因为该应用程序需要快速使用图像,而我的印象是写入/读取核心数据或文件与使用内存时相比,iOS 上的速度较慢(如果我错了,请纠正我)

【问题讨论】:

  • 虽然我不熟悉 xcode,但通常程序解决内存不足的方法是将其分页到磁盘(但这会减慢程序的速度)。除此之外,您还必须更改编译设置或程序设置。
  • 感谢您指出这一点。这个应用程序需要快速访问图像,所以我没有考虑将存储到文件/核心数据作为选项,只是更新了问题以反映这一点
  • 虽然我不能回答你关于它为什么会崩溃的问题(因为你没有发布代码)我可以告诉你,我认为将所有图像存储在一个数组中的设计不是一个好主意.您有什么理由需要始终保持分配的每个图像空间?存储你的图像,并在你去的时候把它们捡起来,完成后把它们放回去(dealloc)。读取图像的访问时间很可能不会对应用速度造成损害。

标签: iphone ios xcode uiimage nsarray


【解决方案1】:

是的,如果您将大量图像存储在可变数组中,那么它会占用大量可用内存。您也可以考虑核心数据。但是在运行时从核心数据存储和检索数据时会发生一些缓慢的功能,但它可以安全地防止内存使用。
对于这种情况,我总是推荐并使用以下功能。我将所有图像缓存在文档目录中,并将其 URL(文件位置)路径保存在 coredata(或任何其他数据库)中。现在在演示时,我从存储当前图像、上一个图像和下一个图像中拍摄了 3 张图像。每当我显示当前图像时,用户可以滚动,他可以流畅地看到下一张或上一张图像。如果用户继续下一张图片,那么我会更改这三张图片。当前图像现在将是我以前的图像,下一个图像将是我当前的图像,我从我的存储位置加载新图像,这将是下一个图像。所以让所有图像都循环播放,我们只使用 3 张图像来处理这个循环。

【讨论】:

  • 不是将图像写入Core Data,而是将它们存储在缓存目录中,并在不再需要时将其删除。该目录也被系统清理。将临时图像数据写入 Core Data 或 SQLite 很慢,尤其是对于变化很大的二进制/图像数据。
  • 好吧,我还没有检查核心数据、SQLite 和文档目录中写入/检索 blob 文件的性能。我只是在应用程序运行时对内存使用的关注中写下我的答案。无论如何,我提到了用于将 blob 文件存储到提问者的文档目录选项。 @Kerni
  • @iAmbitious 在 Core Data 或任何其他数据库中缓存图像而不是文件系统,这对于性能来说是很糟糕的,并且在某些情况下还会显着增加内存压力。
  • @bbum,是的,你是对的。它在某些情况下效果很好,而在某些情况下效果不佳。但是苹果没有给我们解决方案(或解决方法)这样的问题,所以我为什么要使用我的方式。
  • @iAmbitious 苹果确实做到了!只需将图像粘贴在数据库旁边的文件系统中,然后将文件的 URL 写入数据库而不是 BLOB。
【解决方案2】:

我遇到了同样的问题。尝试了不同的方法,最终决定存储 NSData 对象数组并即时转换为 UIImage。

for (NSString *imageFile in directoryList) {
    NSString *fileLocation = [imageFolder stringByAppendingPathComponent:imageFile];
    NSData *imageData = [NSData dataWithContentsOfFile:fileLocation];
    if (imageData) {
        [images addObject:imageData];
    } else {
        [Util trace:@"cannot get image data for image named: %@", fileLocation];
    }

然后更新您的图像:

 -(void)updateImageView:(id)sender
{       
    UIImage *anImage = [UIImage imageWithData:[images safeObjectAtIndex:nextImage] ];
    [imageView setImage:anImage];
    nextImage++;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-01
    • 2016-03-25
    • 2016-08-05
    • 2012-11-06
    • 2011-03-27
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多