Ios – Customizing core data generated accessors

core-dataiosobjective c

I have set up a simple core data schema, where item objects are added to list objects. After generating classes, core data has generated the standard accessors, including a couple of ways to add items to a list (list.addItemsObjects and list.addItems:).

I also want to add a 'dateAdded' NSDate to each item. Now, I could manually set this every time I create an object, since core data will provide me with an item.dateAdded accessor. But really, I would prefer that this is handled by the list itself, since the implementation will never change. So every time I call list.AddItemObject, I would like it to set the dateAdded attribute of the item at the same time. I guess I would also need to do the same in the inverse, so that item.setList also sets the dateAdded.

I am not sure how to do this. Should I try to redefine the existing core data-generated accessors? If so, how do I do this (is there someway to call the original implementation inside my custom code, such that the inverse relationship is handled, and any other core data necessities)? Or is there some better way to customize these methods?

Best Answer

You can override the core data generated accessors. You have to pay attention to a few special things like calling willChangeValueForKey and didChangeValueForKey, but other than that overriding the accessors is pretty much the same as always.

Read the Apple documentation: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdAccessorMethods.html

It's explained clearly with lots of examples. Just pay attention to the difference between one-to-one and one-to-many relations.

You do not need to implement the inverse functionality, this is done by Core Data. If you call list.AddItem, then item.setList will automatically be called for you.

So just add your desired code to the item.setList accessor. That way, you guarantee that everytime an item is added to a list the date is updated accordingly. Don't bother with the list-accessors.

Your code would be something like:

- (void)setList:(List *)value
{
    [self willChangeValueForKey:@"list"];
    [self setPrimitiveValue:[NSDate date] forKey:@"dateAdded"]; // use setValue:forKey: if you need KVO for dateAdded
    [self setPrimitiveValue:value forKey:@"list"];
    [self didChangeValueForKey:@"list"];
}

EDIT I've given it another thought and you might want to know the following:

If you customize the list methods (ie addItemObject), you'll also need to customize setItems. Also, if your item is added to a list which happens not to be the list you customized, your custom code is of course not called.

On the other hand, if you customize the setList method, the code is not called if there are no changes for the item.

For example, if you call

[list addItems:[NSSet setWithObject:item]];
[list addItemsObject:item];

then the item's setList accessor will only be called once! Calls directly to item.setList are always called, even if nothing changed.

Related Topic