title: UITableView crashes after trying to delete a cell the *second* time
body: <p>another weird problem with the iPhone SDK here.</p>
  
  <p>I have a <code>UITableView</code> which contains a custom <code>UITableViewCell</code>. This table gets its data from a mutable array, which in turn pulls it from a Core Data storage.</p>
  
  <p><strong>The problem:</strong> If I enter editing mode and delete a cell, it works for the first time - the cell is successfully removed from the <code>UITableView</code> and the Core Data database. However, if I attempt to <strong>delete another cell, the application crashes after clicking the Delete button for the row</strong> (the one that actually fires the action, not the button that rotates itself to reveal its partner).</p>
  
  <p>This is my code for the <code>UITableView</code> delegate method corresponding to the deletion of rows:</p>
  
  <pre><code>- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
      if ( editingStyle == UITableViewCellEditingStyleDelete ) {
          NSManagedObject *dream = [dreamsArray objectAtIndex:indexPath.row]; 
          [managedObjectContext deleteObject:dream];
  
          [dreamsArray removeObjectAtIndex:indexPath.row];
          // removing from instance field array works fine, but...
          [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
          // ... crash right here
  
          NSError *error = nil;
          if ( ![[self managedObjectContext] save:&amp;error] )
              NSLog(@"DreamsViewController:140 %@", error);
      }
  }
  </code></pre>
  
  <p>I tracked down the problematic method to find <code>deleteRowsAtIndexPaths:withRowAnimation:</code> was (surprisingly) the culprit. I have tried exiting the editing mode, visiting another view, and revisiting this table to delete another, but this didn't work, either.</p>
  
  <hr />
  
  <p><strong>Update:</strong> I have added a test to ensure that an incorrect row value is not given to the UITableView after deleting an element, causing it to crash. Modified code:</p>
  
  <pre><code>- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
      if ( editingStyle == UITableViewCellEditingStyleDelete ) {
          NSManagedObject *dream = [dreamsArray objectAtIndex:indexPath.row];
          [managedObjectContext deleteObject:dream];
  
          // outputs right before a cell is deleted
          NSLog(@"before\tarray\t%d", [dreamsArray count]);
  
          [dreamsArray removeObjectAtIndex:indexPath.row];
          [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
  
          NSError *error = nil;
          if ( ![[self managedObjectContext] save:&amp;error] )
              NSLog(@"DreamsViewController:129 %@", error);
      }
  }
  
  - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
      // outputs after a cell is deleted
      NSLog(@"after\tarray\t%d", [dreamsArray count]);
      return [dreamsArray count];
  }
  </code></pre>
  
  <p>The debug console showed no sort of logic error with the cell's removal (and the removal of its corresponding object):</p>
  
  <pre><code>** pressed "Delete" for the first time **
  2009-09-21 16:47:12.567 xxx[774:20b] before array   11
  2009-09-21 16:47:12.568 xxx[774:20b] after  array   10
  
  ** pressed "Delete" on another cell after first deletion finished **
  2009-09-21 16:47:17.685 xxx[774:20b] before array   10
  2009-09-21 16:47:17.686 xxx[774:20b] after  array   9
  ** after this output, CRASH occurs **
  </code></pre>
  
  <hr />
  
  <p><strong>Update:</strong> Here is the stack trace:</p>
  
  <pre><code>#0  0x94292688 in objc_msgSend ()
  #1  0x016c867d in -[UITableView dequeueReusableCellWithIdentifier:] ()
  #2  0x000038c4 in -[DreamsViewController tableView:cellForRowAtIndexPath:] (self=0x3e1e380, _cmd=0x29cfb18, tableView=0x401b800, indexPath=0x3e4ece0) at /Users/hans/Projects/xxx/Classes/DreamsViewController.m:85
  #3  0x016cee60 in -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:withIndexPath:] ()
  #4  0x016c6a97 in -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:] ()
  #5  0x01866a18 in -[_UITableViewUpdateSupport(Private) _setupAnimationsForExistingOffscreenCells] ()
  #6  0x01869a28 in -[_UITableViewUpdateSupport initWithTableView:updateItems:oldRowData:newRowData:oldRowRange:newRowRange:context:] ()
  #7  0x016d6a2b in -[UITableView(_UITableViewPrivate) _updateWithItems:withOldRowData:oldRowRange:newRowRange:context:] ()
  #8  0x016d6757 in -[UITableView(_UITableViewPrivate) _endCellAnimationsWithContext:] ()
  #9  0x016c8a77 in -[UITableView deleteRowsAtIndexPaths:withRowAnimation:] ()
  #10 0x00003ec3 in -[DreamsViewController tableView:commitEditingStyle:forRowAtIndexPath:] (self=0x3e1e380, _cmd=0x29cfaa0, tableView=0x401b800, editingStyle=UITableViewCellEditingStyleDelete, indexPath=0x3e4e380) at /Users/hans/Projects/xxx/Classes/DreamsViewController.m:125
  #11 0x016c66fc in -[UITableView(UITableViewInternal) animateDeletionOfRowWithCell:] ()
  #12 0x0167f459 in -[UIApplication sendAction:to:from:forEvent:] ()
  #13 0x016e2ba2 in -[UIControl sendAction:to:forEvent:] ()
  #14 0x016e4dc3 in -[UIControl(Internal) _sendActionsForEvents:withEvent:] ()
  #15 0x016e3b0f in -[UIControl touchesEnded:withEvent:] ()
  #16 0x01698e33 in -[UIWindow _sendTouchesForEvent:] ()
  #17 0x0168281c in -[UIApplication sendEvent:] ()
  #18 0x016890b5 in _UIApplicationHandleEvent ()
  #19 0x0001def1 in PurpleEventCallback ()
  #20 0x00843b80 in CFRunLoopRunSpecific ()
  #21 0x00842c48 in CFRunLoopRunInMode ()
  #22 0x0001c7ad in GSEventRunModal ()
  #23 0x0001c872 in GSEventRun ()
  #24 0x0168a003 in UIApplicationMain ()
  #25 0x00005461 in main (argc=1, argv=0xbfffef54) at /Users/hans/Projects/xxx/main.m:14
  </code></pre>
  
  <p>So, after looking through the stack trace, it looks like <code>dequeueReusableCellWithIdentifier:</code> has something to do with this problem, too. Here is the code that calls that method, though I don't see anything wrong with this, either..</p>
  
  <pre><code>- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
      static NSString *cellID = @"dreamCell";
  
      DreamTableCell *cell = (DreamTableCell *)[tableView dequeueReusableCellWithIdentifier:cellID];
      if ( cell == nil )
          cell = [[[DreamTableCell alloc] initWithFrame:CGRectZero reuseIdentifier:cellID] autorelease];
  
      Dream *dream = [dreamsArray objectAtIndex:indexPath.row];
      [cell dreamLabel].text = [dream dreamContent];
  
      [dateFormatter setDateFormat:@"dd"];
      cell.dayLabel.text = [dateFormatter stringFromDate:[dream date]];
  
      [dateFormatter setDateFormat:@"HH:mm"];
      cell.timeLabel.text = [dateFormatter stringFromDate:[dream date]];
  
      return cell;
  }
  </code></pre>