views:

43

answers:

3

I have a core data model with blog groups, blogs, and posts. A blog group has a to-many relationship to blogs, and each blog has a to-many relationship to posts. A post has an attribute "hasBeenRead." Both the blog and the blog group have a attributes "numberUnreadPosts."

I'd like to know the best practice for propagating the number of unread posts up through each relationship. For instance, if I read a post, I'd like to decrease the number of unread posts by one in both the blog and the blog group. Thanks!

A: 

This sounds like a job for Fetched Properties

dontGoPlastic
Or maybe not.. Quoth the documentation you linked to: *"but with the important constraint that it is not dynamic. If objects in the destination entity are changed, you must reevaluate the fetched property to ensure it is up-to-date."*
ohhorob
A: 

Without using fetched properties (which I haven't done - maybe it's the right way), I'd go upwards from Posts. Create a fetch request for entity Post with a predicate for hasBeenRead == NO. Iterating over the resulting array use the inverse relationship to identify the Blog owning each post and BlogGroup owning each Blog and create two dictionaries.

First dictionary has Post->Blog's unique name as key, if there is no entry for that then you create and store [NSValue valueWithInt:1] for the key else increment what's there. Second dictionary is the same but has Post->Blog->BlogGroup's id as key. Unread count for either Blog or BlogGroup is found by looking at the value stored for the relevant key.

You would need to do the complete count once when your program starts and then follow the relationships and update your counts when you change a post from unread to read..

Adam Eberbach
+1  A: 

There are a couple of ways to do this.

KVO observer

Your BlogGroup could watch for changes on the Blog entity -numberUnreadPosts property and when it changes it can update itself.

Likewise, your Blog can watch for changes on the Post entity -hasBeenRead property and when it changes it can update itself which will propagate up to the BlogGroup.

The problem with this design is that it assumes that the BlogGroup and Blog entities are both in memory (because you would turn the observer on in the -awakeFromFetch method). This may not always be the case and I find it best not to rely on that situation.

Propagate the update

When a Post changes the -hasBeenRead property you can override the setter and have it call it's parent (Blog) and tell it about the change. Blog would then update it's own unread count and tell the BlogGroup that it has updated.

This design is far more consistent and is unlikely to fail. However it can have unforeseen consequences because of the ripple. When you change a post a number of objects get fetched into memory to be updated.

Or don't worry about it

A third option is that only the post actually has the value. You could then produce a convenience method on both the Blog and the BlogGroup that merely counts the unread from the objects below.

This is pretty simple to do but it is not an observable property so may not work in your design.

The design of your application will determine which design works better for you. If you know that the BlogGroup and Blog will always be realized when you are working with a post then option one is a better solution imho.

Marcus S. Zarra
Thanks for the reply. I think memory restrictions may end up dictating the direction I go. I was originally doing a propagate, similar to what you suggested, but it's expensive since lots of objects end up in memory at once. I'll give the third option a shot, thanks again!
Drewsmits