为什么加载超过一兆字节的图像会消耗我 iPhone 的所有内存?
我正在编写一个应用程序,需要同时在内存中保存大约 40 个 44 kb JPEG。 我听说应用程序在触发内存不足警告之前可以使用大约 22 MB 的空间,所以我很确定它应该能够做到这一点。 然而,一旦我传递了加载的兆字节,这些消息就会开始在控制台中弹出:
Mon Jun 8 16:37:19 unknown configd[21] : kernel memory event (90), free: 374, active: 1736, inactive: 959, purgeable: 0, wired: 6260 Mon Jun 8 16:37:20 unknown configd[21] : kernel memory event (95), free: 363, active: 876, inactive: 492, purgeable: 0, wired: 6241 Mon Jun 8 16:37:20 unknown SpringBoard[22] : Memory level is critical (5%). No apps to kill. Will kill SpringBoard Mon Jun 8 16:37:24 unknown SpringBoard[22] : Jetsaming SpringBoard...
然后它将我转回主屏幕。
这是我用来加载图像的代码:
#define NUM_IMAGES 40
@interface MyClass : NSObject {
UIImageView* imageView;
UIImage* loadedImages[NUM_IMAGES];
}
- (void)initImages;
@property (nonatomic, retain) IBOutlet UIImageView* imageView;
@end
@implementation MyClass
@synthesize imageView;
- (void)initImages {
int i;
for (i = 0; i < NUM_IMAGES; i++) {
loadedImages[i] = [UIImage imageNamed:[NSString stringWithFormat:IMAGE_FORMAT, i+1]];
}
imageView.image = loadedImages[0];
}
@end
我在这里做错了什么吗? iPhone应用程序真的只能使用1兆字节的内存吗?
I'm writing an application that needs to hold around forty 44 kb JPEGs in memory at once. I've heard that applications can use around 22 megabytes before triggering a low memory warning, so I'm pretty sure it should be able to do this. However, once I pass around a megabyte loaded, these messages start popping up in the console:
Mon Jun 8 16:37:19 unknown configd[21] : kernel memory event (90), free: 374, active: 1736, inactive: 959, purgeable: 0, wired: 6260 Mon Jun 8 16:37:20 unknown configd[21] : kernel memory event (95), free: 363, active: 876, inactive: 492, purgeable: 0, wired: 6241 Mon Jun 8 16:37:20 unknown SpringBoard[22] : Memory level is critical (5%). No apps to kill. Will kill SpringBoard Mon Jun 8 16:37:24 unknown SpringBoard[22] : Jetsaming SpringBoard...
Then it dumps me back to the home screen.
Here's the code I'm using to load the images:
#define NUM_IMAGES 40
@interface MyClass : NSObject {
UIImageView* imageView;
UIImage* loadedImages[NUM_IMAGES];
}
- (void)initImages;
@property (nonatomic, retain) IBOutlet UIImageView* imageView;
@end
@implementation MyClass
@synthesize imageView;
- (void)initImages {
int i;
for (i = 0; i < NUM_IMAGES; i++) {
loadedImages[i] = [UIImage imageNamed:[NSString stringWithFormat:IMAGE_FORMAT, i+1]];
}
imageView.image = loadedImages[0];
}
@end
Is there something I'm doing wrong here? Can iPhone applications really only use a megabyte of memory?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当您加载压缩图像(例如 JPEG 图像)时,它通常会被解压缩(因为这是需要执行的操作,以便您可以对图像执行一些有用的操作,例如显示或操作它)。
未压缩的图像肯定会大于 JPEG 格式压缩图像所占用的 44 KiB(大约 3 或 4 字节乘以宽度和高度)。 因此,内存耗尽的速度比仅查看 JPEG 大小时想象的要快。
如果您确实只需要将 JPEG 保存在内存中(并且对它们不执行任何操作,只需保存它们),您可以考虑将原始字节流存储在内存中,然后仅在您真正需要时将其作为图像加载。
但可能还有其他选择,具体取决于您需要做什么。 您真的需要一次将所有图像存入内存吗? 您可以推迟加载单个图像直到需要它(并在那时卸载其他图像)以节省内存吗? 您是否只需要每个可以缓存的图像中的某些信息(之后您就不再需要图像本身了)? ETC。 ...
When you load a compressed image, such as a JPEG image it will usually be uncompressed (since that is what needs to be done so that you can do something useful with the image, such as displaying or manipulating it).
The uncompressed image will definitely be larger than the 44 KiB the compressed image in JPEG form occupies (roughly 3 or 4 bytes multiplied by width and height). Therefore you run out of memory faster than you'd think when just looking at the JPEG sizes.
If you really only need to hold the JPEGs in memory (and do nothing with them, just holding them) you may consider just storing the raw byte stream in memory then and loading it as an image only when you really need it.
But there may be other alternatives, depending on what you need to do. Do you really need all images in memory at once? Can you defer loading a single image until it is needed (and unload others at that time) to conserve memory? Do you only need certain information out of each image which can be cached (and after which you wouldn't need the image itself anymore)? etc. ...
imageNamed:
将解压缩图像数据并缓存未压缩的数据。 我相信如果您使用 imageWithContentsOfFile: 就会没问题,因为该方法只会存储压缩数据,在绘图时即时对其进行解码。请参阅SO问题的答案 消除 UIImage imageNamed: FUD
具体来说,您应该能够做到:
imageNamed:
will uncompress the image data and cache the uncompressed data. I believe you'll be fine if you useimageWithContentsOfFile:
because that method will only store the compressed data, decoding it on the fly when drawing.See the answer for the SO question Dispelling the UIImage imageNamed: FUD
Specifically, you should be able to do: