title: Assertion failure in UITableView 1070
body: <p>Update: sometimes I get the error message</p>
  
  <pre><code>2013-03-27 19:23:23.094  *** Assertion failure in -[TableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-2372/UITableView.m:1070
  
  2013-03-27 19:23:31.280 [53301:c07] CoreData: error: Serious application error.  Exception was caught during Core Data change processing.  This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification.  Invalid update: invalid number of rows in section 0.  The number of rows contained in an existing section after the update (4) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). with userInfo (null)
  2013-03-27 19:23:31.281 [53301:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0.  The number of rows contained in an existing section after the update (4) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
  </code></pre>
  
  <p>I have an app which fetches most of it's data from the remote service, and persists it using core data.
  I'm writing a view which shows a collection of objects in <code>UITableView</code> with infinite scroll
  [Offtopic: One would think that it is fairly typical, but turns out there are at least 20 ways to do that...] </p>
  
  <p>In my <code>viewDidLoad</code> I construct the fetch request, with a fixed small limit, 0 offset, and a fixed batch size. I initiate the <code>NSFetchedResultsController</code> with that request, <code>nil</code> for cache name and <code>nil</code> for the <code>sectionNameKeyPath</code> and call performFetch. Then I attach the data source which takes data from <code>NSFetchedResultsController</code> in a typical way (I only ever have one section)</p>
  
  <pre><code>- (NSInteger) tableView:(UITableView *)tableView
    numberOfRowsInSection:(NSInteger)section
  {
      return [[fetchController.resultsController sections][section]
              numberOfObjects];
  }
  
  - (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
  {
      return 1;
  }
  </code></pre>
  
  <p>So far so good, I can see my objects pulled out of DB. The idea is that user sees persisted stuff straight away, until new data comes from network.</p>
  
  <p>Then, inside <code>performBlock</code> on a background <code>ManagedObjectContext</code> (which has main UI ManagedObjectContext as a parent) I perform a network fetch, convert the objects to the core data and push them to the main UI context. That works all right as well.</p>
  
  <p>Trouble starts when <code>NSFetchResultsController</code> starts getting notifications about new objects arriving. I have a typical boilerplate, which is mentioned in several books and in the apple's own documentation:</p>
  
  <pre><code>- (void)controller:(NSFetchedResultsController*)controller
  didChangeObject:(id)anObject
  atIndexPath:(NSIndexPath*)indexPath
  forChangeType:(NSFetchedResultsChangeType)type
  newIndexPath:(NSIndexPath*)newIndexPath
  {
      switch(type) {
          case NSFetchedResultsChangeInsert:
              [self.table insertRowsAtIndexPaths:@[newIndexPath]
                        withRowAnimation:UITableViewRowAnimationFade];
              break;
          case NSFetchedResultsChangeDelete:
              [self.table deleteRowsAtIndexPaths:@[indexPath]
                        withRowAnimation:UITableViewRowAnimationFade];
              break;
          case NSFetchedResultsChangeUpdate:
              [self.delegate
               populateCell:[self.table cellForRowAtIndexPath:indexPath]
               indexPath:indexPath
               ];
              break;
          case NSFetchedResultsChangeMove:
              [self.table deleteRowsAtIndexPaths:@[indexPath]
                        withRowAnimation:UITableViewRowAnimationFade];
              [self.table insertRowsAtIndexPaths:@[newIndexPath]
                        withRowAnimation:UITableViewRowAnimationFade];
              break;
      }
  }
  </code></pre>
  
  <p>Now things start to get weird. Firstly, the <code>newIndexPath</code> I get is strange: sometimes it's 0, sometimes it's 18, sometimes it's 28. It appears to be non-deterministic (my <code>fetchLimit</code> and <code>batchSize</code> are set to 20)</p>
  
  <p>Furthermore, when <code>insertRowsAtIndexPath</code> is called the assertion is thrown from the cocoa layer: </p>
  
  <pre><code>*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-2380.17/UITableView.m:1070
  </code></pre>
  
  <p>No, there are no further explanations. Isn't it marvellous?</p>
  
  <p>I take it there is some inconsistency between the number of rows or sections UITableView expects and actually gets. Are there any suggestions in which way should I look? Without UITableView source code I have no idea where to start looking. Currently I'm tempted to re-implement analogue of <code>NSFetchedResultsController</code> myself so that I can see what's actually going on.</p>