Note that there are some explanatory texts on larger screens.

plurals
  1. POCrashes with UITableView
    primarykey
    data
    text
    <p>I am displaying an array objects in a UITableView with inserts, updated and deletes and occasionally I get the exception below even though I am carefully handling the changes. I have the full code example on GitHub.</p> <p><a href="https://github.com/brennanMKE/TableMaddness" rel="nofollow">https://github.com/brennanMKE/TableMaddness</a></p> <p>This sample project uses objects which implement NSCoding and NSCopying as well as isEqual so that updating the table with inserts, updates and deletes can simulate what I am doing in a real app which is having the same problem. I am avoiding using Core Data which would use NSFetchedResultsController so I'd like know if there is something I should use if I am not using Core Data.</p> <p><strong>Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-2903.23/UITableView.m:1330 2013-11-25 14:43:20.217 TableMaddness[13411:70b] 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 (4), 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).'</strong></p> <p>Below is the related code.</p> <pre><code> // determine items which need to be inserted, updated or removed NSMutableArray *inserts = [@[] mutableCopy]; NSMutableArray *deletes = [@[] mutableCopy]; NSMutableArray *reloads = [@[] mutableCopy]; // look for inserts for (NSUInteger row=0; row&lt;fetchedItems.count; row++) { SSTItem *item = fetchedItems[row]; if (![self.currentItems containsObject:item]) { // inserts are items which are not already in self.items [inserts addObject:[NSIndexPath indexPathForRow:row inSection:0]]; } else { NSUInteger otherIndex = [self.currentItems indexOfObject:item]; SSTItem *otherItem = [self.currentItems objectAtIndex:otherIndex]; if (![item.modified isEqualToDate:otherItem.modified]) { [reloads addObject:[NSIndexPath indexPathForRow:row inSection:0]]; } } } // look for deletes for (NSUInteger row=0; row&lt;self.currentItems.count; row++) { SSTItem *item = self.currentItems[row]; if (![fetchedItems containsObject:item]) { [deletes addObject:[NSIndexPath indexPathForRow:row inSection:0]]; } } static NSString *lock = @"LOCK"; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (kDelay / 4) * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ // lock is required to prevent inconsistencies when changing view orientation during rotation @synchronized(lock) { self.currentItems = fetchedItems; NSUInteger numberOfRowsInSection = [self tableView:self.tableView numberOfRowsInSection:0]; DebugLog(@"numberOfRowsInSection: %li", numberOfRowsInSection); DebugLog(@"self.items: %li", self.currentItems.count); MAAssert(self.currentItems.count == numberOfRowsInSection, @"Match is required"); if (inserts.count || deletes.count || reloads.count) { [self.tableView beginUpdates]; #ifndef NDEBUG for (NSIndexPath *indexPath in inserts) { DebugLog(@"Inserting at %li", (long)indexPath.row); } for (NSIndexPath *indexPath in deletes) { DebugLog(@"Deleting at %li", (long)indexPath.row); } for (NSIndexPath *indexPath in reloads) { DebugLog(@"Reloading at %li", (long)indexPath.row); } #endif [self.tableView insertRowsAtIndexPaths:inserts withRowAnimation:UITableViewRowAnimationAutomatic]; [self.tableView deleteRowsAtIndexPaths:deletes withRowAnimation:UITableViewRowAnimationAutomatic]; [self.tableView reloadRowsAtIndexPaths:reloads withRowAnimation:UITableViewRowAnimationAutomatic]; [self.tableView endUpdates]; } } index++; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, kDelay * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ [self runNextUpdate]; }); }); </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload