Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><code>NSFetchedResultsController</code> gets terribly confused if you use an <code>NSFetchRequest</code> when preparing your cell in response to <code>tableView:cellForRowAtIndexPath:</code>. If you don't execute a <code>NSFetchRequest</code>, all is well. However, if you do, it triggers <code>NSFetchedResultsController</code> to perform further change notifications, which does bad things to <code>UITableView</code>.</p> <p>The workaround for this is to set <code>includesPendingChanges = NO</code> on your NSFetchRequest.</p> <p>I have opened a radar issue about this -- problem id <code>14048101</code> -- with a detailed example and sample app. This bug reproduces on iOS 5.1, 6.0, and 6.1.</p> <p>In my sample app, I added logging to Xcode's CoreData template to log enter/leave of <code>NSFetchedResultsController</code> delegate methods. When I insert + delete objects on the network context, the logging shows:</p> <p>01: => (before) mergeChangesFromContextDidSaveNotification 02: => (enter) controllerWillChangeContent count=4 03: &lt;= (leave) controllerWillChangeContent count=4 04: didChangeObject type=1 indexPath=(null) newIndexPath= 2 indexes [0, 0] 05: => (enter) controllerDidChangeContent count=5</p> <p>At this point, all is good. <code>controllerDidChangeContent:</code> has been called to process the 1 insert, which calls <code>[tableView endUpdates]</code>, which calls <code>tableView:cellForRowAtIndexPath:</code>, which calls <code>configureCell:atIndexPath:</code>.</p> <p>06: => (enter) configure cell at row 0</p> <p>At this point, <code>configureCell:atIndexPath:</code> creates an <code>NSFetchRequest</code> and calls <code>[self.managedObjectContext executeFetchRequest:error:]</code> -- here begins the badness. Executing this fetch request triggers the processing of the remaining changes in the context (1 delete and 3 updates) before processing of the insert has finished (we entered <code>controllerDidChangeContent:</code> on line #05 and don't leave until line #16).</p> <p>07: => (enter) controllerWillChangeContent count=5 08: &lt;= (leave) controllerWillChangeContent count=5 09: didChangeObject type=2 indexPath= 2 indexes [0, 4] newIndexPath=(null) 10: didChangeObject type=4 indexPath= 2 indexes [0, 2] newIndexPath=(null) 11: didChangeObject type=4 indexPath= 2 indexes [0, 1] newIndexPath=(null) 12: didChangeObject type=4 indexPath= 2 indexes [0, 3] newIndexPath=(null) 13: => (enter) controllerDidChangeContent count=4</p> <p>At this point, the framework is making a re-entrant call to<code>controllerDidChangeContent:</code>.</p> <p>14: &lt;= (leave) controllerDidChangeContent count=4 15: &lt;= (leave) configure cell at row 0 16: &lt;= (leave) controllerDidChangeContent count=4 17: &lt;= (after) mergeChangesFromContextDidSaveNotification</p> <p>At this point, you can see in the UI that: (1) a new cell has been added, (2) 3 cells were updated, and (3) the deleted cell is still visible, which is wrong.</p> <p>After further action in the UI, I typically get an <code>Assertion failure</code> or message sent to an invalid object exception.</p> <p>My sample app is available at <a href="https://github.com/peymano/CoreDataFetchedResultsController" rel="noreferrer">https://github.com/peymano/CoreDataFetchedResultsController</a></p>
    singulars
    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. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      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