Note that there are some explanatory texts on larger screens.

plurals
  1. PONSManagedObjectContext does not notify observer of changes for transients
    primarykey
    data
    text
    <p>I am trying to clean up some transient property recalculation events. In development I have just used a very broad stroke of updating on almost all changes. Now I am trying to determine the best practice, checking for relevant keys and updating as little as needed. My application objects are loaded with dozens of calculations using child and parent attributes where a single change can result in many cascading recalculations.</p> <p>I thought I understood fairly well, referring to Apple Documentation <a href="https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueObserving/Articles/KVODependentKeys.html#//apple_ref/doc/uid/20002179-BAJEAIEE" rel="nofollow noreferrer">here</a> and I have experimented with patterns seen on some other StackOverflow posts such as <a href="https://stackoverflow.com/questions/16738126/core-data-emitting-kvo-notifications-for-transient-derived-properties">this</a> one by @Marcus S. Zarra. I see Marcus also posted an article on the subject <a href="http://www.cimgf.com/2011/10/14/parent-watching-its-child/" rel="nofollow noreferrer">here</a>.</p> <p>What I have currently is this:</p> <pre><code>#pragma mark _ worksheetTotal (transient) +(NSSet *)keyPathsForValuesAffectingWorksheetTotal { // local, non-transient, dependent keys here return [NSSet setWithObjects:@"dailySustenance", nil]; } -(void)updateWorksheetTotal { NSDecimalNumber *lineItemTotal = [self.items valueForKeyPath:@"@sum.lineHoursCost"]; NSDecimalNumber *total = [lineItemTotal decimalNumberByAdding:self.dailySustenance]; [self setWorksheetTotal:total]; } -(void)setWorksheetTotal:(NSDecimalNumber *)newWorksheetTotal { if ([self worksheetTotal] != newWorksheetTotal) { [self willChangeValueForKey:@"worksheetTotal"]; [self setPrimitiveWorksheetTotal:newWorksheetTotal]; [self didChangeValueForKey:@"worksheetTotal"]; } } -(NSDecimalNumber *)worksheetTotal { [self willAccessValueForKey:@"worksheetTotal"]; NSDecimalNumber *result = [self primitiveWorksheetTotal]; [self didAccessValueForKey:@"worksheetTotal"]; return result; } </code></pre> <p>I am thinking this is straight out of the documentation use case but my observers are not getting notified of the the changes to worksheetTotal.</p> <p>When a change is made to a lineItem, that notification is received and responds <code>updateWorksheetTotal</code> is called here. I expect this would trigger another notification by the context that worksheetTotal has now changed, but it does not. I have tried numerous variations and combinations of code I have seen but nothing I do seems to make the <code>NSManagedObjectContext</code> consider my update to <code>worksheetTotal</code> to be a change worth reporting to observers.</p> <p>What am I missing here?</p> <p>Here is the relevant code for listening for the change in Parent object.</p> <pre><code>- (void) objectContextDidChange: (NSNotification *) notification { NSSet *updatedObjects = [[notification userInfo] objectForKey:NSUpdatedObjectsKey]; // Next look for changes to worksheet that may affect our calculated fields NSPredicate *worksheetPredicate = [NSPredicate predicateWithFormat:@"entity.name == %@ &amp;&amp; estimate == %@", @"LaborWorksheet", self]; NSPredicate *materialsPredicate = [NSPredicate predicateWithFormat:@"entity.name == %@ &amp;&amp; estimate == %@", @"MaterialLineItems", self]; NSPredicate *combinedPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:[NSArray arrayWithObjects:worksheetPredicate, materialsPredicate, nil]]; NSSet *myWorksheets = [updatedObjects filteredSetUsingPredicate:combinedPredicate]; // These are the relevant keys in this estimates labor and materials worksheet NSSet *relevantKeys = [NSSet setWithObjects:@"worksheetTotal", @"totalEquipmentcost", nil]; BOOL clearCache = NO; if (myWorksheets.count != 0) { for (NSManagedObject *worksheet in myWorksheets) { NSLog(@"got some"); // Here is where it fails, worksheetTotal is not in changedValues.allKeys. It is an empty set. // Not sure how that could be when I got it from updatedObjects set of userInfo. How could it have no changed values? NSSet *changedKeys = [NSSet setWithArray:worksheet.changedValues.allKeys]; if ([changedKeys intersectsSet:relevantKeys]) { clearCache = YES; NSLog(@"found some, set to clear cache"); // no need to continue checking break; } } } if (clearCache) { // I would update dependent keys here but it is never reached } } </code></pre>
    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.
 

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