views:

341

answers:

2

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?

+12  A: 

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. ...

Joey
Thanks for the explanation, it helped.I've made it keep the JPEG data for the full-resolution images in memory and display quarter-resolution images while changing or loading images.Thanks!
A: 

imageNamed: will uncompress the image data and cache the uncompressed data. I believe you'll be fine if you use imageWithContentsOfFile: 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:

[UIImage imageWithContentsOfFile:[[UIBundle mainBundle] pathForResource:@"filename" ofType:@"jpeg"]];
Daniel Dickison