2

Say you have a core data entity,

public class CDPerson: NSManagedObject

You get new info from the net ... a field changes,

p.name = 'Debbie'

That CDPerson item is "touched" and hence,

your NSFetchedResultsController will trigger,

perfect.

But say CDPerson can belong to CDAddress

In core data, a change in CDAddress does not trigger a change in CDPerson

But. When an address is touched, you DO want to touch the relevant person items,

so that results controllers will know CDPerson has been changed.

How to "touch" a cd entity?

One rubbish solution, assuming you have an unimportant field,

let touch = p.creationDate
p.creationDate = touch

Alternately you could add an Int64 and

p.touchyInt = a random number, or increment, etc

These are poor solutions

Is there actually a way to "touch" a core data entity, for results controllers?

This seems to be critical in propagating changes in related entities.

It's hard to believe there is no solution for this.


PS related QA: NSFetchedResultsController with relationship not updating

"NSFetchedResultsController with relationship not updating"

Community
  • 1
  • 1
Fattie
  • 27,874
  • 70
  • 431
  • 719
  • There are KVO functions, `willChangeValueForKey` and `didChangeValueForKey`, which might (I’m not sure) be sufficient to trigger the FRC to recognise a change, even if you don’t actually change the value for the key. But they also need an arbitrary key to be specified, so not sure they’re much better than your solution. – pbasdf Feb 18 '20 at 12:31
  • I feel your pain. Unfortunately, I think the solution that you came up with is the best one. On a side note, I'm not sure how set you are on using core data, but for future reference, in Realm, if you update a field on a related object, you will get change notifications on the parent objects. – Rob C Feb 26 '20 at 05:07
  • @Rob you may be right - it may be the only way :/ Crazy stuff ... I do use realm also but, it has its own problems :/ Also the thing with core data is the link to collection views and table views - that is "the" reason to use core data, I suppose :/ – Fattie Feb 26 '20 at 10:41
  • Seems related also to https://stackoverflow.com/questions/62142358/is-it-possible-to-source-an-up-to-date-snapshot-from-an-nsfetchedresultscontroll Even though one is talking about diffable data sources and the other is not, it's the same problem of being notified when something down the hierarchy changes, I think. – matt Jun 15 '20 at 00:57
  • @matt , thanks for the note, TBH I don't understand the whole issue about Snapshots, why you would use them, or the issues involved :) My guess is this question stackoverflow.com/questions/62142358 is just misguided, the OP need only "trivially" (rofl) use a fetched results controller in the normal way. :/. IDK ... – Fattie Jun 15 '20 at 02:08
  • it seems that basically every programmer who gets in to coredata (this was certainly true of me!) asks the question "Uh, are you kidding, doesn't it work with relationships?". Here's the latest victim :) https://stackoverflow.com/q/62374472/294884 – Fattie Jun 15 '20 at 02:09

1 Answers1

0

Core Data recognizes changes by the firing of -willChangeValueForKey: and -didChangeValueForKey: as the comment from @pbasdf indicated. You can call only -didChangeValueForKey: if you want but I would really do both.

Those calls also work on relationships. So in your Address object, you can touch both the value to be changed and the relationship to the person:

- (void)setCity:(NSString*)cityString
{
  [self willChangeValueForKey:@"city"];
  [self willChangeValueForKey:@"person"];
  _city = cityString;
  [self didChangeValueForKey:@"person"];
  [self didChangeValueForKey:@"city"];
}

With an end result of the NSFetchedResultsController being told that the associated person object has changed and the cell should be re-drawn.

Marcus S. Zarra
  • 46,571
  • 9
  • 101
  • 182
  • Hi Marcus. I ended up trying this solution some time ago, on a database with extremely complex relationships. I ended up with some circularity that really caused problems, and ended up ditching this solution. Eventually just reloaded certain rows, sections or the whole tableview based on changes in NSManagedObjectContextObjectsDidChangeNotification. – SAHM Feb 26 '20 at 00:58
  • Now, I am working on some delayed iOS 13 updates, and I feel like the best approach might be to use NSDiffableDataSource and update the snapshot with the changed objects from NSManagedObjectContextObjectsDidChangeNotification - before applying the snapshot. Thoughts on this approach? – SAHM Feb 26 '20 at 00:59
  • Marcus, thanks for that explanation and the example call. Unfortunately as @SAHM mentioned I too have had troubles trying to do this. But maybe it's the only real solution. It's just incredible there is no basic way to do this in CD :/ – Fattie Feb 26 '20 at 10:39
  • @SAHM I will try to investigate what you mention about diffables. – Fattie Feb 26 '20 at 10:39
  • @Fattie Great. And I meant to say UICollectionViewDiffableDataSource and UITableViewDiffableDataSource. Maybe we can put our heads together and figure this out. – SAHM Feb 26 '20 at 12:00
  • @Fattie have you made any progress on this by any chance? – SAHM Mar 28 '20 at 20:30