2
votes

I'm writing a Core Data based Cocoa app for recipes. I have an Ingredient entity, and want to create a ingredientSubstitutes To Many relationship to other Ingredients, but I'm getting errors either when setting the relationship or when saving the store that I can't figure out. Here's the Entity description:

Ingredient
Attributes:
  ingredientName type:String
Relationships:
  ingredientSubstitutes destination:Ingredient inverse:ingredientSubstitutes

In my Nib I have 3 array controllers:

  • All ingredients AC
  • Available substitutes AC
  • Selected ingredient substitutes AC

I have 3 table views that each display the contents of these array controllers. I then have a button to add one ingredient as a subsitute for another, that is bound as follows

Button bindings
Target: All Ingredients AC.selection 
        Selector Name: addIngredientSubstitutesObject:
Argument: Available Substitutes AC.seletion

With this setup, as soon as I click the add button, the app throws unrecognized selector sent to instance exception: "-[_NSControllerObjectProxy entity]: unrecognized selector sent to instance", as if Ingredient doesn't recognize addIngredientSubstitutesObject. I added a proxy method to make sure that's the selector that's not recognized, and that is indeed the problem.

After trying a bunch of things and getting no where, as an experiment, I then changed the model, so that ingredientSubstitutes has no inverse:

Ingredient
Attributes:
  ingredientName type:String
Relationships:
  ingredientSubstitutes destination:Ingredient inverse:*none*

When I run this the add is successful, and all the tables update accordingly, but on save, I get a different unrecognized selector and the app throws an exception:

-[_NSControllerObjectProxy _isKindOfEntity:]: unrecognized selector sent to instance

Any suggestions as to what might be going on? Am I taking the wrong approach?

1

1 Answers

0
votes

Figured it out, this thread helped tip me off: Core Data Programmatically Adding a to-many Relationship

Basically, binding the target to the Array Controller's selection meant that the target object was an Array Controller's Proxy object for an Ingredient, not an actual Ingredient, which apparently does not respond to the To Many accessors that Ingredient does. I solved this by instead implementing a method in the app delegate that gets the actual objects and can use the To Many accessors:

- (void)addSubstituteForSelectedIngredient:(OFIngredient *)ingredient
{
  OFIngredient *selectedIngredient = [[self.allIngredientsArrayController selectedObjects] objectAtIndex:0];
  OFIngredient *selectedSubstitute = [[self.availableSubsArrayController selectedObjects] objectAtIndex:0];

  [selectedIngredient addIngredientSubsObject:selectedSubstitute];
}

Note that NSArrayController's - (id) selection method (which I tried before, as mentioned in the original description) returns a proxy object, so you must use (NSArray *)selectedObjects!