Understanding Instruments memory allocation log on iOS

Viewed 6442

I have built an iOS app that is almost done, however, I have recently experienced that it crashes after while due to "Memory pressure". So I started profiling the memory allocations in Instruments and sure, the app does use quite a lot of memory and it only seems to increase during usage.

However, relatively new to Instruments memory allocation I am not quite able to decipher where 52 % of the allocations are made, as seen in the screenshot below:

enter image description here

It has obviously got something to do with Core Animation, but what exactly is hard for me to determine, so I thought that some clever minds out there might know the answer to that.

Breadcrumb:

My app uses custom segues, when moving between view controllers, where a lot of animation is taking place. Here is an example:

@interface AreaToKeyFiguresSegue : UIStoryboardSegue

@end

...

@implementation AreaToKeyFiguresSegue

- (void)perform
{
    [self sourceControllerOut];
}

- (void)sourceControllerOut
{
    AreaChooserViewController *sourceViewController = (AreaChooserViewController *) [self sourceViewController];
    KeyFigureViewController *destinationController = (KeyFigureViewController *) [self destinationViewController];

    double ratio = 22.0/sourceViewController.titleLabel.font.pointSize;

    sourceViewController.titleLabel.adjustsFontSizeToFitWidth = YES;

    [UIView animateWithDuration:TRANSITION_DURATION delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{

        // Animate areaChooser
        sourceViewController.areaChooserScrollView.alpha = 0;
        sourceViewController.areaScrollViewVerticalSpaceConstraint.constant = -300;

        sourceViewController.backButtonVerticalConstraint.constant = 20;
        sourceViewController.backButton.transform = CGAffineTransformScale(sourceViewController.backButton.transform, ratio, ratio);
        sourceViewController.backButton.titleLabel.textColor = [UIColor redKombitColor];

        sourceViewController.backArrowPlaceholderVerticalConstraint.constant = 14;
        sourceViewController.backArrowPlaceholder.alpha = 1;

        sourceViewController.areaLabelVerticalConstraint.constant = 50;
        sourceViewController.areaLabel.alpha = 1;

        [sourceViewController.view layoutIfNeeded];

    } completion:^(BOOL finished) {
        [destinationController view]; // Make sure destionation view is initialized before animating it
        [sourceViewController.navigationController pushViewController:destinationController animated:NO]; // Push new viewController without animating it

        [self destinationControllerIn]; // Now animate destination controller
    }];
}

- (void)destinationControllerIn
{
    AreaChooserViewController *sourceViewController = (AreaChooserViewController *) [self sourceViewController];
    KeyFigureViewController *destinationController = (KeyFigureViewController *) [self destinationViewController];

    destinationController.keyFigureTableViewVerticalConstraint.constant = 600;
    destinationController.keyFigureTableView.alpha = 0.0;
    destinationController.allFavoritesSegmentedControl.alpha = 0.0;
    [destinationController.view layoutIfNeeded];
    [sourceViewController.segueProgress setHidden:YES];
} 

@end

And whenever a view controller is to be popped, I simply do the reverse thing:

- (IBAction)goBack:(id)sender
{
    [UIView animateWithDuration:TRANSITION_DURATION delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{

        [self.keyFigureTableView setAlpha:0];
        self.keyFigureTableViewVerticalConstraint.constant = 700;
        [self.allFavoritesSegmentedControl setAlpha:0];
        [self.view layoutIfNeeded];
    } completion:^(BOOL finished) {
        [self.navigationController popViewControllerAnimated:NO]; // Pop viewController without animating it
    }];
}

Edit:

Most of the memory allocation takes place when pushing a view controller, even if it has already been displayed before. I.e. going from

A -> B -> C

B <- C

B -> C

where "->" = push and "<-" = pop, each "->" allocates more memory and "<-" never releases any.

Further details

I have no zombies and no leaks according to Instruments. Static analysis also gives nothing. My app just keeps allocating memory until it finally crashes.

Around 70 % of my memory allocation happens in the following call stack, which has nothing to do with my code (inverted call tree):

enter image description here

4 Answers
Related