Memory leak with a lot of big images in iPad

2019-06-06 13:27发布

问题:

I'm trying to store UIImage datas in NSArray, actually 60 images, each with size of 300kb. Then, I'm trying to animate that images in UIImageView.

My code:

    NSMutableArray *arr = [[NSMutableArray alloc] init];
    for (int i=0; i<61; ++i) {
        [arr addObject:[UIImage imageNamed:[NSString stringWithFormat:@"%i.png", i]]];
    }

    img.animationImages = arr;
    img.animationDuration = 1.5;
    img.contentMode = UIViewContentModeBottomLeft;
    [img startAnimating];


When I test it in iPad Simulator 4.3, it works fine.
When I want to test it on my device (iPad 1), application crashes.

Note: App does not crashes if I comment this code: [img startAnimating];

1. What could be the problem? I think it is memory problem...?!
2. Can I store a loooots of UIImages in NSArray?

回答1:

Your png files may have 300KB, but this is a compressing format.

To get an idea of the size of the Image itself you should multiply the width, height and bytes per pixel.

i.e. If an image has the size 1024 * 1024 and RGBA model, the images itself has an size of 4MB in the memory. And this is just one image. If you have 300 it is about 120MB.

Note: this is only a rough rule of thumb, but it gives you an idea.

So you should keep path-names in the array and load the image only if need, and thumbnails should be resized and stored on the disk as files. Do not just scale the UIImageView.

Here's a great article with code about resizing.



回答2:

I solved the app crash problem with alternative way: I tried to use simple NSTimer. For each iteration I set n'th image to UIImageView:

  • I have UIImageView in xib file, pointing to img variable.
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:.03 
                            target:self 
                            selector:@selector(tiktak) 
                            userInfo:nil repeats:YES];
int n = 0;

-(void)tiktak {
    n++;
    img.image = [UIImage imageNamed:
                   [NSString stringWithFormat:@"Blue Menu_%i.png", n]];
    if(nn == 60) nn = 0;
}


Animation is amazing. I've also tested it in Activity Monitor, CPU usage is 6% and less.



回答3:

I would not advise you store that many UIImages in an NSArray, its way too heavy and inefficient. From where are these images from (bundle, internet, device's gallery)?

Edit: I don't know how you want it to look, but you can build the array with the names of the UIImages, and then load the UIImage and show it. Like this:

for(i=0;i<60;i++){
 NSString *nameOfPicture=[NSString stringWithFormat:@"picture_%d",i+1]
 [array addObject:nameOfPicture];
}