title: Possible memory leak in UIViewController with UITableView
body: <p>I have a UIViewController thats presented modally. When I watch the memory allocations Instrument, the memory usage increases when the view is presented, but when it's exited the memory isn't released.
  If I keep opening and closing the view, the memory just keeps getting higher.
  Instruments doesn't report a memory leak!
  What could be causing this? The View Controller code is below (I've skipped the didSelectRow code).
  Dealloc is always called.</p>
  
  <p>EDIT - I am using ARC</p>
  
  <p>.h</p>
  
  <pre><code>#import &lt;UIKit/UIKit.h&gt;
  @class OutlineTextUILabel;
  
  @interface StoreViewController : UIViewController &lt;UITableViewDelegate, UITableViewDataSource&gt; {
  
      int starCount;
      NSMutableArray *_singleUseArray;
      NSMutableArray *_fullUseArray;
  
  }
  
  @property (weak, nonatomic) IBOutlet UITableView *tableView;
  @property (weak, nonatomic) IBOutlet OutlineTextUILabel *starCountLbl;
  - (IBAction)exitBtnPressed:(id)sender;
  </code></pre>
  
  <p>.m</p>
  
  <pre><code>#import "StoreViewController.h"
  #import "NSUserDefaults+MPSecureUserDefaults.h"
  #import "PowerUpCell.h"
  #import "OutlineTextUILabel.h"
  #import "PowerUpSingleton.h"
  #import "PowerUp.h"
  
  #define kPrefsNumberOfStars             @"numberOfStars"
  
  @interface StoreViewController ()
  
  @end
  
  @implementation StoreViewController
  @synthesize tableView = _tableView;
  @synthesize starCountLbl;
  
  #pragma mark View Methods
  
  - (void)viewDidLoad
  {
      [super viewDidLoad];
  
      // Display star count
      NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
      BOOL valid = NO;
      starCount = [prefs secureIntegerForKey:kPrefsNumberOfStars valid:&amp;valid];
      if (!valid) {
          NSLog(@"Stars Tampered With!");
          self.starCountLbl.text = @"Err";
      } else {
          self.starCountLbl.text = [NSString stringWithFormat:@"%d",starCount];
      }
  
      // Tableview setup
      CGRect frame2 = CGRectMake(0, 0, 320, 40);
      UIView *footer = [[UIView alloc] initWithFrame:frame2];
      footer.backgroundColor = [UIColor clearColor];
      self.tableView.tableFooterView = footer;
      self.tableView.opaque = NO;
      self.tableView.backgroundView = nil;
  }
  
  - (void)viewWillAppear:(BOOL)animated
  {
      [super viewWillAppear:YES];
  
      if (![[PowerUpSingleton sharedList] refreshArray]) {
          NSLog(@"Error, %s",__FUNCTION__);
      } else {
          [self performSelectorOnMainThread:@selector(workOutSingleUseToDisplay) withObject:nil waitUntilDone:YES];
          [self performSelectorOnMainThread:@selector(workOutFullUseToDisplay) withObject:nil waitUntilDone:YES];
          [self.tableView reloadData];
      }
  }
  
  - (void)workOutSingleUseToDisplay
  {
      _singleUseArray = [[NSMutableArray alloc] init];
      for (PowerUp *pu in [[PowerUpSingleton sharedList] sharedArray]) {
          if (!pu.fullUnlock) {
              [_singleUseArray addObject:pu];
          }
      }
  }
  
  - (void)workOutFullUseToDisplay
  {
      _fullUseArray = [[NSMutableArray alloc] init];
      for (PowerUp *pu in [[PowerUpSingleton sharedList] sharedArray]) {
          if (pu.prefFullName != nil) {
              [_fullUseArray addObject:pu];
          }
      }
  
  }
  
  - (void)didReceiveMemoryWarning
  {
      [super didReceiveMemoryWarning];
      // Dispose of any resources that can be recreated.
  }
  
  - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  {
      return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
  }
  
  - (void)viewDidUnload {
      [self setTableView:nil];
      [self setStarCountLbl:nil];
      [super viewDidUnload];
  }
  
  #pragma mark TableView Setup Methods
  
  - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
  {
      return 2;
  }
  
  - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
  {
      if (section == 0) {
          return @"Single Use";
      } else if (section == 1) {
          return @"Use forever";
      }
  
      return nil;
  }
  
  - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  {
      if (section == 0) {
          return [_singleUseArray count];
      } else if (section == 1) {
          return [_fullUseArray count];
      }
  
      return 0;
  }
  
  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  {
      NSString *cellIdentifier;
      if (indexPath.section == 0) {
          cellIdentifier = @"powerUpCellSingleUse";
      } else if (indexPath.section == 1) {
          cellIdentifier = @"powerUpCell";
      }
  
      PowerUpCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
      if (cell == nil) {
          cell = [[PowerUpCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
      }
  
      if (indexPath.section == 0) {
          PowerUp *tmpPU = [_singleUseArray objectAtIndex:indexPath.row];
          cell.descriptionLbl.text = tmpPU.displayName;
          int cost = tmpPU.costSingle;
          cell.costLbl.text = [NSString stringWithFormat:@"%d",cost];
          if (cost &gt; starCount) {
              cell.costLbl.textColor = [UIColor redColor];
          } else {
              cell.costLbl.textColor = [UIColor blueColor];
          }
          int howMany = tmpPU.numberOwned;
          cell.howManyLbl.text = [NSString stringWithFormat:@"%d",howMany];
  
      } else if (indexPath.section == 1) {
          PowerUp *tmpPU = [_fullUseArray objectAtIndex:indexPath.row];
          cell.descriptionLbl.text = tmpPU.displayName;
          int cost = tmpPU.costFull;
          cell.costLbl.text = [NSString stringWithFormat:@"%d",cost];
          if (cost &gt; starCount) {
              cell.costLbl.textColor = [UIColor redColor];
          } else {
              cell.costLbl.textColor = [UIColor blueColor];
          }
          if (tmpPU.fullUnlock) {
              cell.costLbl.textColor = [UIColor greenColor];
              cell.costLbl.text = @"---";
          }
      }
  
      return cell;
  }
  
  #pragma mark -
  
  - (IBAction)exitBtnPressed:(id)sender
  {
      [self dismissModalViewControllerAnimated:YES];
  }
  
  - (void)dealloc
  {
      NSLog(@"%s",__FUNCTION__);
      self.tableView = nil;
      self.starCountLbl = nil;
  }
  
  @end
  </code></pre>
  
  <p>EDIT -------------
  Something seems not to be right. I've added an NSLog to the cell alloc, and it's never called, even though the cells are created!</p>
  
  <pre><code>PowerUpCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
      if (cell == nil) {
          NSLog(@"new cell");
          cell = [[PowerUpCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
      }
  </code></pre>
  
  <p>EDIT July 1st ------
  I've added a Navigation controller and now use push instead of modal and this problem is still here.
  I've taken heap shots with Instruments by moving back and forward between views a few times and it seems maybe the cells are still hanging around, as this screenshot shows gesture recogniser still around from a previous load of the view.
  <img src="https://i.stack.imgur.com/5hG06.png" alt="screen shot"></p>