title: My modal keeps eating memory
body: <p>I am experiencing a rather serious issue with my iPhone app using ARC.</p>
  
  <p>I have a viewcontroller (lets call this A). This viewcontroller opens a navigationcontroller as a modal which runs through 3 different viewcontrollers (lets call these 1, 2 and 3). After viewing number 3 the navigationcontroller closes and we're back to A again.</p>
  
  <p>So the flow is: A opens navigationcontroller and goes through 1->2->3 and then it closes again.</p>
  
  <p>Every time I go through this flow i lose memory. I've searched through all my files looking for any retain og strong properties, un-invalidated timers or similar in order to solve this problem.</p>
  
  <p>I have one idea, which might be the problem. At viewcontroller 1 i present a animation using coreanimation and a sprite. I'm using a implementation made by someone else. It seems like if i disable the animations the memory used seems quite constant (and thereby no memory loss). I have modified the implementation a bit to use ARC. This is the implementation I use for my sprite animations:</p>
  
  <p><strong><code>MCSpriteLayer.h</code></strong></p>
  
  <pre><code>//
  //  MCSpriteLayer.h
  //
  //  Created by Miguel Angel Friginal on 8/20/10.
  //  Copyright 2010 Mystery Coconut Games. All rights reserved.
  //
  
  #import &lt;Foundation/Foundation.h&gt;
  #import &lt;QuartzCore/QuartzCore.h&gt;
  
  @interface MCSpriteLayer : CALayer {
      unsigned int sampleIndex;
  }
  
  // SampleIndex needs to be &gt; 0
  @property (nonatomic) unsigned int sampleIndex; 
  
  // For use with sample rects set by the delegate
  + (id)layerWithImage:(CGImageRef)img;
  - (id)initWithImage:(CGImageRef)img;
  
  // If all samples are the same size 
  + (id)layerWithImage:(CGImageRef)img sampleSize:(CGSize)size :(int)useRetina;
  - (id)initWithImage:(CGImageRef)img sampleSize:(CGSize)size;
  
  // Use this method instead of sprite.sampleIndex to obtain the index currently displayed on screen
  - (unsigned int)currentSampleIndex; 
  
  
  @end
  </code></pre>
  
  <p><strong><code>MCSpriteLayer.m</code></strong></p>
  
  <pre><code>//
  //  MCSpriteLayer.m
  //
  //  Created by Miguel Angel Friginal on 8/20/10.
  //  Copyright 2010 Mystery Coconut Games. All rights reserved.
  //
  
  #import "MCSpriteLayer.h"
  
  
  @implementation MCSpriteLayer
  
  @synthesize sampleIndex;
  
  #pragma mark -
  #pragma mark Initialization, variable sample size
  
  
  - (id)initWithImage:(CGImageRef)img;
  {
      self = [super init];
      if (self != nil)
      {
          self.contents = (__bridge id)img;
          sampleIndex = 1;
      }
  
      return self;
  }
  
  
  + (id)layerWithImage:(CGImageRef)img;
  {
      MCSpriteLayer *layer = [(MCSpriteLayer*)[self alloc] initWithImage:img];
      return layer;
  }
  
  
  #pragma mark -
  #pragma mark Initialization, fixed sample size
  
  
  - (id)initWithImage:(CGImageRef)img sampleSize:(CGSize)size;
  {
      self = [self initWithImage:img];
      if (self != nil)
      {
          CGSize sampleSizeNormalized = CGSizeMake(size.width/CGImageGetWidth(img), size.height/CGImageGetHeight(img));
          self.bounds = CGRectMake( 0, 0, size.width, size.height );
          self.contentsRect = CGRectMake( 0, 0, sampleSizeNormalized.width, sampleSizeNormalized.height );
      }
  
      return self;
  }
  
  
  + (id)layerWithImage:(CGImageRef)img sampleSize:(CGSize)size :(int)useRetina;
  {
  
      CGSize newSampleSize;
      if(useRetina == 1) {
          // Supporting retina displays
          if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] &amp;&amp;
              ([UIScreen mainScreen].scale == 2.0)) {
              newSampleSize = CGSizeMake(size.width*2, size.height*2);
          } else {
              newSampleSize = size;
  
          }
      } else
          newSampleSize = size;
  
      MCSpriteLayer *layer = [[self alloc] initWithImage:img sampleSize:newSampleSize];
      return layer;
  }
  
  
  #pragma mark -
  #pragma mark Frame by frame animation
  
  
  + (BOOL)needsDisplayForKey:(NSString *)key;
  {
      return [key isEqualToString:@"sampleIndex"];
  }
  
  
  // contentsRect or bounds changes are not animated
  + (id &lt; CAAction &gt;)defaultActionForKey:(NSString *)aKey;
  {
      if ([aKey isEqualToString:@"contentsRect"] || [aKey isEqualToString:@"bounds"])
          return (id &lt; CAAction &gt;)[NSNull null];
  
      return [super defaultActionForKey:aKey];
  }
  
  
  - (unsigned int)currentSampleIndex;
  {
      return ((MCSpriteLayer*)[self presentationLayer]).sampleIndex;
  }
  
  
  // Implement displayLayer: on the delegate to override how sample rectangles are calculated; remember to use currentSampleIndex, ignore sampleIndex == 0, and set the layer's bounds
  - (void)display;
  {
      if ([self.delegate respondsToSelector:@selector(displayLayer:)])
      {
          [self.delegate displayLayer:self];
          return;
      }
  
      unsigned int currentSampleIndex = [self currentSampleIndex];
      if (!currentSampleIndex)
          return;
  
      CGSize sampleSize = self.contentsRect.size;
      self.contentsRect = CGRectMake(
          ((currentSampleIndex - 1) % (int)(1/sampleSize.width)) * sampleSize.width, 
          ((currentSampleIndex - 1) / (int)(1/sampleSize.width)) * sampleSize.height, 
          sampleSize.width, sampleSize.height
      );
  }
  
  
  @end
  </code></pre>
  
  <p>Is this implementation somehow not realeasing correctly or retaining anything? Thanks in advance.</p>
  
  <p><strong>Update</strong>
  - I am using Instruments to measure the memory. I am using the Memory Monitor where I keep an eye on the Physical Memory Free
  - The image is created like this:</p>
  
  <pre><code>NSString *path = [[NSBundle mainBundle] pathForResource:@"round_start.png" ofType:nil];
  CGSize fixedSize = CGSizeMake(320, 480);
  mascot = [MCSpriteLayer layerWithImage:[UIImage imageWithContentsOfFile:path].CGImage sampleSize:fixedSize :0];
  mascot.frame = CGRectMake(ANIMATION_X, ANIMATION_Y, ANIMATION_WIDTH, ANIMATION_HEIGHT);
  [self.view.layer addSublayer:mascot2];
  
  CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"sampleIndex"];
  anim.delegate = self;
  anim.fromValue = [NSNumber numberWithInt:1];
  anim.toValue = [NSNumber numberWithInt:52];
  anim.duration = ANIMATION_DURATION;
  anim.repeatCount = 1;
  
  [mascot addAnimation:anim forKey:nil];
  </code></pre>
  
  <p>- I've been experiencing with closing the modal with</p>
  
  <pre><code>[self dismissModalViewControllerAnimated:YES];
  </code></pre>
  
  <p>and</p>
  
  <pre><code>[self.navigationController dismissModalViewControllerAnimated:YES];
  </code></pre>