I have a problem with memory and images that I am animating. First thing first, I am using ARC. On my initial screen I have about 60 images to animate. I am using this code for animation:
NSMutableArray *images = [[NSMutableArray alloc] init];
int animationImageCount = 61;
for (int i = 1; i < animationImageCount; i++) {
[images addObject:[UIImage imageNamed:[NSString stringWithFormat:@"s-%d", i]]];
}
self.fullAnimatedImage = [UIImage imageNamed:[NSString stringWithFormat:@"s-%d", animationImageCount - 1]];
self.animatedImageView.image = self.fullAnimatedImage;
self.animatedImageView.animationImages = [NSArray arrayWithArray:images];
self.animatedImageView.animationDuration = images.count/30;
self.animatedImageView.animationRepeatCount = 1;
[self.animatedImageView startAnimating];
// since there is no official callback method when UIImageView animation completes,
// we can just call a method after animation time has passed
[self performSelector:@selector(animationFinished) withObject:nil
afterDelay:self.animatedImageView.animationDuration];
The problem is that memory consumption is about 300 MB and of course it crashes on iPhone 4. When I comment out that part of code, memory consumption is about 40 MB, that's ok. I've tried setting image property to nil and nothing. I've tried to put it in @autoreleasepool {}
but it does not release it's content. Do you have any idea how to optimise this?
You should try replacing [UIImage imageNamed:]
with [UIImage imageWithContentsOfFile:]
.
From the docs:
If you have an image file that will only be displayed once and wish to ensure that it does not get added to the system’s cache, you should instead create your image using imageWithContentsOfFile:. This will keep your single-use image out of the system image cache, potentially improving the memory use characteristics of your app.
How big is each image that you are loading (pixel wise and file size wise)?
Your best bet is to optimise the images to reduce their file sizes/memory requirements. Try using jpg instead of png if you haven't yet. If they are part of a video sequence you can safely reduce their quality further without having a knockoff on perceived quality.
So after a period of time, I decided to go different way. From 60 images, I have created 10 images. I do not have every image for every object, but one images for all objects. For example, if you have 3 cars, and image for each car, and another n images for moving every three point to the left, that's now one image for all three cars. For same objects, I have created one whole image. After that, I have created image view for each image. I needed to know for every image what was image object final position. For example, car is going from right to left. So I have placed that one image with all my cars on the right, out of view bounds. And that is the logic for every other image. After that I just animate UIImageViews position. I hope it helps someone.
The problem in your code is with the basic approach. You simply cannot hold all the decoded images in memory at the same time. I wrote a specific blog post on this subject which you can read here. The solution is to use a different approach, so that you only hold 1 frame of decoded image data in memory at once. That means frames of data need to be dynamically loaded as needed.