Originally created by @colinmorelli on GitHub (Oct 1, 2016).
There may be some nuances that I'm missing here, but as far as I can tell, implementing ObjectMonitor without a dependency on NSFetchedResultsController should be fairly straightforward. Primarily, it would consist of subscribing to NSManagedObjectContextDidSaveNotification on the desired context, and observing the inserted/updated/deleted objects to see if any of them match the condition self.objectID == providedObject.objectID
There are a few benefits I see here:
Almost certainly more performant. There's no overhead needed to track sections, ordering, etc when using this method that NSFetchedResultsController almost certainly contains
Support for macOS < 10.12
This is most important for me (and the reason I'm asking for this): the ability to avoid an initial fetch for the object (elaborated below)
Consider a case with a UITableView backed by an NSFetchedResultsController, where each row represents entity A that has a relation to another entity, B. Due to "limitations" in NSFetchedResultsController, there's no direct way to update a cell when the B entity for one of the records changes, without forcing a change to the A record that can be observed by the FRC. To get around this, it's possible to use an ObjectMonitor in each of the cells, that monitors the B entity for changes. The issue here is that every invocation of cellForRowAtIndexPath (to build a cell in the table) will then have to execute another query to fetch the current value of B, which is actually already known, just to be notified of future changes. Effectively, this translates a single query (select * from a join b) into an N+1 (even if, internally, Core Data can optimize a lot of this away to a cache lookup, it has to pay the cost of predicate parsing and setting up all of its internal structures to figure that out).
By breaking out of the FRC (for ObjectMonitor only), this case could be vastly improved. Ask the DataStack for an objectMonitor for an existing entity, for which you pay only the cost of constructing an object an adding an observer (both of which are "free", relative to the cost of setting up an FRC and performing the initial fetch). From that point forward, it simply notifies the application whenever the given entity changes by observing notifications.
If it's something you'd consider adding I may be able to attempt to work on a PR for it.
Originally created by @colinmorelli on GitHub (Oct 1, 2016).
There may be some nuances that I'm missing here, but as far as I can tell, implementing `ObjectMonitor` without a dependency on `NSFetchedResultsController` should be fairly straightforward. Primarily, it would consist of subscribing to `NSManagedObjectContextDidSaveNotification` on the desired context, and observing the inserted/updated/deleted objects to see if any of them match the condition `self.objectID == providedObject.objectID`
There are a few benefits I see here:
1. Almost certainly more performant. There's no overhead needed to track sections, ordering, etc when using this method that `NSFetchedResultsController` almost certainly contains
2. Support for macOS < 10.12
3. This is most important for me (and the reason I'm asking for this): the ability to avoid an initial fetch for the object (elaborated below)
Consider a case with a UITableView backed by an `NSFetchedResultsController`, where each row represents entity A that has a relation to another entity, B. Due to "limitations" in `NSFetchedResultsController`, there's no direct way to update a cell when the B entity for one of the records changes, without forcing a change to the A record that can be observed by the FRC. To get around this, it's possible to use an `ObjectMonitor` in each of the cells, that monitors the B entity for changes. The issue here is that every invocation of `cellForRowAtIndexPath` (to build a cell in the table) will then have to execute another query to fetch the current value of B, which is actually already known, just to be notified of future changes. Effectively, this translates a single query (select \* from a join b) into an N+1 (even if, internally, Core Data can optimize a lot of this away to a cache lookup, it has to pay the cost of predicate parsing and setting up all of its internal structures to figure that out).
By breaking out of the FRC (for ObjectMonitor only), this case could be vastly improved. Ask the DataStack for an objectMonitor for an existing entity, for which you pay only the cost of constructing an object an adding an observer (both of which are "free", relative to the cost of setting up an FRC and performing the initial fetch). From that point forward, it simply notifies the application whenever the given entity changes by observing notifications.
If it's something you'd consider adding I may be able to attempt to work on a PR for it.
I have considered this myself, just didn't find too much of a need of it (for now). If this was to be implemented however, I'm thinking KVO would be way more performant than handling NSManagedObjectContextDidSaveNotification directly.
Due to "limitations" in NSFetchedResultsController, there's no direct way to update a cell when the B entity for one of the records changes, without forcing a change to the A record that can be observed by the FRC. To get around this, it's possible to use an ObjectMonitor in each of the cells, that monitors the B entity for changes.
Have you tried implementing keysPathsForValuesAffectingValueForKey() on your relationship entity? Doing so might let NSFetchedResultsController get notified of relationship changes.
@JohnEstropia commented on GitHub (Oct 3, 2016):
I have considered this myself, just didn't find too much of a need of it (for now). If this was to be implemented however, I'm thinking KVO would be way more performant than handling `NSManagedObjectContextDidSaveNotification` directly.
> Due to "limitations" in NSFetchedResultsController, there's no direct way to update a cell when the B entity for one of the records changes, without forcing a change to the A record that can be observed by the FRC. To get around this, it's possible to use an ObjectMonitor in each of the cells, that monitors the B entity for changes.
Have you tried implementing `keysPathsForValuesAffectingValueForKey()` on your relationship entity? Doing so _might_ let NSFetchedResultsController get notified of relationship changes.
I have tried implementing keysPathsForValuesAffectingValueForKey() on relationship entity, but it does not work. NSFetchedResultsController does not get notified of relationship changes.
@ruslanskorb commented on GitHub (Mar 24, 2017):
I have tried implementing `keysPathsForValuesAffectingValueForKey()` on relationship entity, but it does not work. `NSFetchedResultsController` does not get notified of relationship changes.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @colinmorelli on GitHub (Oct 1, 2016).
There may be some nuances that I'm missing here, but as far as I can tell, implementing
ObjectMonitorwithout a dependency onNSFetchedResultsControllershould be fairly straightforward. Primarily, it would consist of subscribing toNSManagedObjectContextDidSaveNotificationon the desired context, and observing the inserted/updated/deleted objects to see if any of them match the conditionself.objectID == providedObject.objectIDThere are a few benefits I see here:
NSFetchedResultsControlleralmost certainly containsConsider a case with a UITableView backed by an
NSFetchedResultsController, where each row represents entity A that has a relation to another entity, B. Due to "limitations" inNSFetchedResultsController, there's no direct way to update a cell when the B entity for one of the records changes, without forcing a change to the A record that can be observed by the FRC. To get around this, it's possible to use anObjectMonitorin each of the cells, that monitors the B entity for changes. The issue here is that every invocation ofcellForRowAtIndexPath(to build a cell in the table) will then have to execute another query to fetch the current value of B, which is actually already known, just to be notified of future changes. Effectively, this translates a single query (select * from a join b) into an N+1 (even if, internally, Core Data can optimize a lot of this away to a cache lookup, it has to pay the cost of predicate parsing and setting up all of its internal structures to figure that out).By breaking out of the FRC (for ObjectMonitor only), this case could be vastly improved. Ask the DataStack for an objectMonitor for an existing entity, for which you pay only the cost of constructing an object an adding an observer (both of which are "free", relative to the cost of setting up an FRC and performing the initial fetch). From that point forward, it simply notifies the application whenever the given entity changes by observing notifications.
If it's something you'd consider adding I may be able to attempt to work on a PR for it.
@JohnEstropia commented on GitHub (Oct 3, 2016):
I have considered this myself, just didn't find too much of a need of it (for now). If this was to be implemented however, I'm thinking KVO would be way more performant than handling
NSManagedObjectContextDidSaveNotificationdirectly.Have you tried implementing
keysPathsForValuesAffectingValueForKey()on your relationship entity? Doing so might let NSFetchedResultsController get notified of relationship changes.@ruslanskorb commented on GitHub (Mar 24, 2017):
I have tried implementing
keysPathsForValuesAffectingValueForKey()on relationship entity, but it does not work.NSFetchedResultsControllerdoes not get notified of relationship changes.@JohnEstropia commented on GitHub (Jan 8, 2020):
ObjectPublishers are now the go to types for this. Closing ticket