0
- (void)viewDidLoad
{
    [super viewDidLoad];

    self.predictionsObjectArray = [[AAPredictions alloc] init];
    self.animationImagesMutableArray = [NSMutableArray new];

    [self.predictionsObjectArray setPredictionsArray:@[@"Probably Not", @"Ask Again", @"I doubt it", @"Unlikely", @"I believe so"]];

    for (int x = 1; x<61; x++) {
        NSMutableString *imageName = [[NSMutableString alloc] init];
        if (x > 9) {
            imageName = [NSMutableString stringWithFormat:@"CB000%i.png", x];
        }
        else {
           imageName = [NSMutableString stringWithFormat:@"CB0000%i.png", x];
        }
        [self.animationImagesMutableArray addObject:[UIImage imageNamed:imageName]];
    }
    self.background_image.animationImages = self.animationImagesMutableArray;
    self.animationImagesMutableArray = NULL;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark Prediction

-(void)makePrediction {
    self.predictionLabel.text = [self.predictionsObjectArray getPrediction];
    [self animateItems];
}

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
    if (flag == true) {
        self.image_button.alpha = 1;
    }
}

-(void)animateItems {
    self.image_button.alpha = 0.0;
    self.background_image.animationRepeatCount = 1;
    if (self.background_image.animationImages == NULL) {
        self.background_image.animationImages = self.animationImagesMutableArray;
    }
    self.background_image.animationDuration = 3;
    [self.background_image startAnimating];
    [self performSelector:@selector(postAnimation) withObject:nil afterDelay:4.25];
}

-(void)postAnimation {
    self.image_button.alpha = 1;
    self.background_image.animationImages = NULL;
}

#pragma mark Actions

-(void) motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event {
    if (self.background_image.isAnimating != true) {
        [self makePrediction];
    }
}

- (IBAction)button_pushed {
    if (self.background_image.isAnimating != true) {
        [self makePrediction];
    }
}
@end

I am new to programming and am doing a class online and had to create a crystalBall app. I wanted to take it a step further and add a button functionality. So that button is basically the crystal ball showing up and disappearing(goes away during animation). The problem i’ve had for the last few days that i can’t get is in the debugger i have all the images stored in memory after the makePrediction function is called… it’s about 187MB. i know it’s not a lot, but the app starts with 27MB. how do i release it from memory then restore the images back into the background_image.animationImages every time that function is called?

Till
  • 27,559
  • 13
  • 88
  • 122
  • Megabytes? Do you mean Kilobytes? 187 MB is ALOT! Where does it increase? After time, or after you push a button? – CaptJak Dec 15 '13 at 00:01
  • byes it does… which i don’t know why again –  Dec 15 '13 at 00:16
  • I don't see how `animateItems` would work the second time your run it, because `viewDidLoad` set `animationImagesMutableArray` to `NULL`, and `postAnimation` set `background_image.animationImages` to `NULL`, too, so those should be the only two references to your array of images, so I don't see how this could possibly work. If the animation is still working the second time, you must have some other reference to the array of images that you have not shared with us. BTW, you should be using `nil`, not `NULL`. – Rob Dec 15 '13 at 02:47
  • BTW, I assume you're using ARC. Also, what are the dimensions of those images? – Rob Dec 15 '13 at 02:50

2 Answers2

2

A couple of thoughts:

  1. Your approach of animating via an array of images will always be an extravagant use of memory. If you do this, you might want to reduce either the number of images, or reduce the dimensions of the individual images.

    To appreciate how much memory is used by this technique, assume 4 bytes per pixel per image. Thus, 60 images at 800px x 800px takes up 146mb. Do not look at the size of the JPG or PNG file to determine how much memory the images take. Those are compressed formats, but when the image is loaded into a UIKit control, it is uncompressed, taking 4 bytes per pixel.

  2. As others have pointed out, the use of imageNamed will cache images, which will prevent memory from being freed when the image is released. You might consider using imageWithContentsOfFile instead. You'll lose the performance gain of the cache, but you shouldn't suffer the memory usage issues it entails.

  3. You might want to give us some idea of what the "crystal ball showing up and disappearing" animation looks like. The question is whether you could achieve the desired animation without having an array of different images.

    Generally you would have only one image (completely eliminating this memory issue), and then animate some animatable property (e.g. the alpha so it fades in and out of view, the frame if you want it to slide in and out or squeeze in and out, transform to scale/move it, etc.). Having only one image, and then animating one of those properties is a more more memory efficient way to handle animation. For example, to have it fade out:

    [UIView animationWithDuration:0.5
                       animations:^{
                           self.crystalBall.alpha = 0.0;
                       }];
    

    You'd have to tell us more about what this animation is supposed to look like for us to help you further.

Bottom line, loading all of those images into memory is extravagant and you want to either minimize the size of each image, reduce the number of images, or completely retire this "array of images" concept and move to some animateWithDuration block-based animation.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
0

So this is an old issue, but imageNamed will cache the image in memory, it's designed for small reusable images like buttons, icons, etc. I think you will see an improvement in memory pressure if you'd use imageWithContentsOfFile which is not cached.

There is a terrific answer on SO that goes into more detail on the issue.

Community
  • 1
  • 1
Dmitry Shevchenko
  • 31,814
  • 10
  • 56
  • 62