Ben Packard
Ben Packard

Reputation: 26476

Custom initializer for an NSManagedObject

According to the docs:

You should not override init. You are discouraged from overriding initWithEntity:insertIntoManagedObjectContext:

and you should instead use awakeFromInsert or awakeFromFetch.

This is fine if all I want to do is set some attribute to the current date or similar, but what if I want to send in another object and set attributes based on its information?

For example, in an NSManagedObject subclass called 'Item', I want an initFromOtherThing:(Thing *)thing, in which the item's name is set to that of the thing. I would like to avoid 'just having to remember' to set the name each time immediately after creating the item, and having to update fifteen different controller classes when I decide that I want Item to also set another default attribute based on Thing. These are actions tied to the model.

How am I meant to handle this?

Upvotes: 2

Views: 1618

Answers (1)

LavaSlider
LavaSlider

Reputation: 2504

I think the best way to handle this is by subclassing the NSManagedObject and then creating a category to hold what you want to add to the object. For example a couple of class methods for uniquing and conveniently creating:

+ (item *) findItemRelatedToOtherThing: (Thing *) existingThing inManagedObjectContext *) context {
    item *foundItem = nil;
    // Do NSFetchRequest to see if this item already exists...
    return foundItem;
}

+ (item *) itemWithOtherThing: (Thing *) existingThing inContext: (NSManagedObjectContext *) context {
    item *theItem;
    if( !(theItem = [self findItemRelatedToOtherThing: existingThing inManagedObjectContext: context]) ) {
        NSLog( @"Creating a new item for Thing %@", existingThing );
        theItem = [NSEntityDescription insertNewObjectForEntityForName: @"item" inManagedObjectContext: context];
        theItem.whateverYouWant = existingThing.whateverItHas;
    }
    return theItem; 
}

Now don't ever call initWithEntity:insertIntoManagedObjectContext: directly just use your convenience class method like:

item *newItem = [item itemWithOtherThing: oldThing inContext: currentContext];

Upvotes: 1

Related Questions