Skip to content

Batch Notification Order

Nick D. edited this page Jul 10, 2013 · 10 revisions

NSFetchedResultsController Notification Order

Based on tests, NSFetchedResultsController sends out its notifications in the following order:

  1. Section Insertions (Final Index)
  2. Section Deletions (Initial Index)
  3. Object Insertions (Final Index Path)
  4. Object Deletions (Initial Index Path)
  5. Object Moves (Initial Index Path to Final Index Path)
  6. Object Updates (Initial Index Path)

If an update causes an object to change its place in the results, an update message is NOT sent. This may have implications for a tableview observing these notifications.

The order of the individual notifications is NOT guaranteed. If the order is indeed deterministic, its pattern is not obvious.

Here is the console output produced by RZCollectionListFetchOrderTests in the demo project's unit tests:

2013-06-20 11:22:20.983 RZCollectionList-Demo[16677:c07] WILL CHANGE
2013-06-20 11:22:20.984 RZCollectionList-Demo[16677:c07] CURRENT CONTENTS: (
    "Jill [0]",
    "Jack [0]",
    "Garfunkel [1]",
    "Simon [1]",
    "Clyde [2]",
    "Bonnie [2]",
    "Jerry [2]",
    "Ben [2]",
    "Nu:Tone [4]",
    "Technicolour [4]"
)
2013-06-20 11:22:20.984 RZCollectionList-Demo[16677:c07] INSERTED SECTION AT INDEX 2
2013-06-20 11:22:20.985 RZCollectionList-Demo[16677:c07] DELETED SECTION AT INDEX 1
2013-06-20 11:22:20.985 RZCollectionList-Demo[16677:c07] DELETED SECTION AT INDEX 0
2013-06-20 11:22:20.985 RZCollectionList-Demo[16677:c07] DELETED SECTION AT INDEX 3
2013-06-20 11:22:20.986 RZCollectionList-Demo[16677:c07] INSERTED OBJECT AT <NSIndexPath 0x843bc40> 2 indexes [2, 1] : Chong [420]
2013-06-20 11:22:20.986 RZCollectionList-Demo[16677:c07] INSERTED OBJECT AT <NSIndexPath 0x8438920> 2 indexes [2, 0] : Cheech [420]
2013-06-20 11:22:20.986 RZCollectionList-Demo[16677:c07] DELETED OBJECT at <NSIndexPath 0x75b2330> 2 indexes [1, 0] : Garfunkel [1]
2013-06-20 11:22:20.987 RZCollectionList-Demo[16677:c07] DELETED OBJECT at <NSIndexPath 0x75b23f0> 2 indexes [1, 1] : Simon [1]
2013-06-20 11:22:20.987 RZCollectionList-Demo[16677:c07] DELETED OBJECT at <NSIndexPath 0x75b2480> 2 indexes [0, 0] : Jill [0]
2013-06-20 11:22:20.987 RZCollectionList-Demo[16677:c07] DELETED OBJECT at <NSIndexPath 0x75b2510> 2 indexes [0, 1] : Jack [0]
2013-06-20 11:22:20.988 RZCollectionList-Demo[16677:c07] MOVED OBJECT FROM <NSIndexPath 0x75b25e0> 2 indexes [3, 0] TO <NSIndexPath 0x84379e0> 2 indexes [0, 0] : Jerry [2]
2013-06-20 11:22:20.988 RZCollectionList-Demo[16677:c07] MOVED OBJECT FROM <NSIndexPath 0x75b26e0> 2 indexes [3, 1] TO <NSIndexPath 0x8437000> 2 indexes [0, 1] : Ben [2]
2013-06-20 11:22:20.988 RZCollectionList-Demo[16677:c07] UPDATED OBJECT AT <NSIndexPath 0x75b27e0> 2 indexes [4, 1] : Technicolour [4]
2013-06-20 11:22:20.989 RZCollectionList-Demo[16677:c07] DID CHANGE
2013-06-20 11:22:20.989 RZCollectionList-Demo[16677:c07] CURRENT CONTENTS: (
    "Jerry [2]",
    "Ben [2]",
    "Clyde [2]",
    "Bonnie [2]",
    "Nu:Tone [4]",
    "Technicolour [4]",
    "Cheech [420]",
    "Chong [420]"
)

RZCollectionList Notification Order

For the sake of providing "causal" notifications to observers, currently RZFetchedCollectionList delays the delivery of Section Removal notifications until the end of a batched update. Otherwise, observers will see that a section is deleted and then potentially try to remove objects from it after the fact, which does not make sense.

Facts:
  • Table- and CollectionViews do not care about order of notifications in a batch. They will figure it out internally.
    • Exception for update notifications. Updates concurrent with other notifications can cause multiple animation exceptions.
    • CollectionList data sources, therefore, do not need to worry about notification order, except for updates.
    • Already proposed to be handled with delayed table updates OR optional delegate method to update cell prior to animation.
Order for Batch Updates

In order to facilitate more "causal" object change notification patterns, all CollectionLists should produce and/or expect notifications in this following order:

  1. Object Deletions (descending by index path)
  2. Section Deletions (descending by section index)
  3. Section Insertions (ascending by section index)
  4. Object Insertions (ascending by index path)
  5. Object Moves (ascending by new index path)
  6. Object Updates (order doesn't matter)
Caveats
  • Filtered collection list requires moves to be split into two phases
    • This is due to the way the filtered list maintains index sets to its source list, which must be modified in a particular order.
    • Remove phase happens right after other removes
    • Insert phase happens right after other inserts
    • More details in the code comments
  • Update messages now send both the original index path (indexPath) and the post-batch-update index path (newIndexPath).
    • This is so any modifiers/observers that care whether an updated object changed position in the batch update can have that info
    • e.g. table view data source can either update cell immediately before animations, or delay and reload the row in another animation set (reloading in the same animation set can lead to double-animation exceptions)