在 iOS 4.0 上使用大图像时应用程序崩溃

Posted

技术标签:

【中文标题】在 iOS 4.0 上使用大图像时应用程序崩溃【英文标题】:App Crashing when using large images on iOS 4.0 【发布时间】:2011-04-10 10:00:39 【问题描述】:

我在滚动视图上显示大图像时遇到了问题,图像大小为 2,4 - 4,7 MB。它在 3GS 和模拟器上运行良好。但每当我尝试在 3G 或 iPod Touch 2G 上运行时,它就会崩溃。

我在网上搜索并找到了“imageNamed is evil”的文章。好的,我将所有图像调用更改为 imageWithContentsOfFile: 但它仍然崩溃,我看到的唯一不同是现在图像在我离开视图后被释放就好了。但是内存使用率还是很高的。

这是 Instruments 的屏幕截图。 第一个高峰是我在启动时显示的视频,然后tableview显示了很多图像,直到那时没有问题。

当我输入 1.1mb - 2576 x 1000 图片时

当我输入一张 4.8mb - 7822 x 1000 的图片时

顺便说一下,该应用在 ios 4 和 3.1.2 上进行了测试

你有什么建议吗?因为这个问题快把我逼疯了。

非常感谢!

【问题讨论】:

我有一个类似的问题:三个 UIImageViews 并排在一个 UIScollView 中。当图像是 JPG(缩放为 1200x1600)时,内存使用量很疯狂:像你的例子一样跳到 30Mb+。 但是,如果我改用 PNG 图像,则内存使用率会很低(并且不会崩溃)。不幸的是,PNG 的大小是在设备上下载和存储的三倍 :-( 【参考方案1】:

我最近在 3G 上测试应用时遇到了同样的问题。我最终缩小了任何大于最大像素数的图像(我发现 200 万像素似乎在我的 3G 上可靠地工作,但 hotpaw2 的回答似乎表明 100 万像素可能是更安全的选择)。

UIImage *image = // ...;
if (image.size.width * image.size.height > MAX_PIXELS) 
    // calculate the scaling factor that will reduce the image size to MAX_PIXELS
    float actualHeight = image.size.height;
    float actualWidth = image.size.width;
    float scale = sqrt(image.size.width * image.size.height / MAX_PIXELS);

    // resize the image
    CGRect rect = CGRectMake(0.0, 0.0, floorf(actualWidth / scale), floorf(actualHeight / scale));
    UIGraphicsBeginImageContext(rect.size);
    [image drawInRect:rect];
    UIImage *imageToDraw = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    // imageToDraw is a scaled version of image that preserves the aspect ratio

Apple 还提供了一个开发照片库应用程序的示例,该应用程序使用 CATiledLayer 来平铺非常大的图像。他们的示例使用已预先切成适当大小的图块的图像。可以在您的 iOS 应用程序中动态地将图像分割成图块,但在设备上这样做非常慢。查看今年 WWDC 的第 104 场会议,了解 PhotoScroller 示例。

【讨论】:

非常感谢,我刚刚查看了您说的照片库。我设法在我的 iPhone 上的 Safari 上渲染了 4mb 图像,现在我要做的是放置一个 web 视图而不是滚动视图,因为我认为 Safari 使用在本机照片库中找到的相同算法。 手指交叉 我也遇到过大图像的问题。目前,我将图像大小调整为 1024x768,因为这些尺寸足以满足我的应用程序。性能提高了,从那以后我没有遇到任何崩溃。 太棒了!非常感谢,我正在以另一种方式缩放图像,但它无法像您的代码一样处理大图像。【参考方案2】:

iPhone 3G 和 iPod Touch 1G/2G 中的 GPU 只能容纳 1k x 1k 纹理,这似乎也用于 2D 图像渲染。任何更大的东西都需要平铺以适应硬件图形渲染器。

3GS 和更新版本具有不同的 GPU,可以支持更大的纹理,从而支持图像。

【讨论】:

我想知道iphone原生相册是怎么做的,你觉得是这样吗? 你能提供任何代码来将图像平铺到其他部分吗? 如果您可以访问 Apple 的开发者网站,请在此处登录:developer.apple.com/videos/wwdc/2010 并通过 iTunes 下载示例代码和会话视频 104(感谢 GreginYEG 提及此会话)。 对于那些寻找会话 104 的人来说,它被称为“设计带有滚动视图的应用程序”。【参考方案3】:

我最终使用了 UIWebView,我不得不使用更小的(以 MB 为单位,而不是尺寸)图像,但它正在运行,唯一的问题是我无法缩放...使用 scalePageToFit 我可以缩放但图像适合水平而不是垂直,那个sux。

我会努力更新这个问题。

如果有人遇到这个问题,我建议使用 webview 或可以更好地处理内存的 three20 图像查看器的适配器版本。

【讨论】:

以上是关于在 iOS 4.0 上使用大图像时应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

使用 iOS 4.0 中的方法时,iOS 3.0 会崩溃吗?

上传大图像时网络连接中止后恢复或重新启动ajax请求?

在行中包含大图像时,如何使 IE 11 尊重表格中的列宽?

在上传大图像时,蛋糕php中的内存分配问题

从文件上传读取网址时图像自动旋转(当它是大图像时)?

在 iOS 4.0 上释放 Autoreleasepool 崩溃(以及在 4.1 上......)