9

Using core data I'd like to fetch some data. My model uses some abstract entities, see attached picture, where QuantifiedIngredient is an abstract class. I'd like to fetch Ingredient entities that have at least one RecipeQuantifiedIngredients, but in the middle is QuantifiedIngredient, which is an abstract class.

How can I do that, how can I test the actual type of an abstract class inside a NSPredicate? Any idea or suggestion?

enter image description here

The only clue I found was: How can you reference child entity name in a predicate for a fetch request of the parent entity?

Would work a custom property in my QuantifiedIngredient to know if it is a RecipeQuantifiedIngredient? For instance isRecipeQuantifiedIngredient?

Thanks a lot for your help.

Community
  • 1
  • 1
Ricardo
  • 2,831
  • 4
  • 29
  • 42

2 Answers2

2

If recipe is required in RecipeQuantifiedIngredient, you could try to make a fetch, that checks, if there is any ingredient.recipe. I think, that will work.

The custom property, in kind of flag, will work for you too. You'll just need to set and unset it whenever you add or delete all the recipeQuantifiedIngredient.

Nikita Pestrov
  • 5,876
  • 4
  • 31
  • 66
  • The actual question if is it possible to cope with inheritance from NSPredicate. I already thought about adding a flag, but from the modeling point of view, it's a nasty solution, although could be a workaround. Thanks anyway. – Ricardo Jun 18 '12 at 22:17
1

I don't want to take the time to translate this into CoreData-speak so here is my thought in SQL:

SELECT * FROM quantifiedIngredients WHERE recipe <> NULL

or something like that. This is essentially Nikita's suggestion of using a flag, except that the 'flag' is the existence of a property. I don't know how CoreData will react when faced with GroceryQuantifiedIngredients that don't have the recipe, I think KVO will throw an exception. You might be so bold as to add a category:

@interface GroceryQuantifiedIngredients (KVOHack)
-(id)recipe;
@end

@implementation GroceryQuantifiedIngredients (KVOHack)
-(id) recipe { return nil; }
@end

This would of course require CoreData to enumerate all quantifiedIngredients, but I presume it will have to do so anyway, and a the return nil should optimize into tiny code. The other consideration is whether this will have a bad effect on the rest of your code; you will have to make that call.

Another idea which pops to mind as I finish this up is to do something like this (I'm getting really loose with my pseudo-code now):

SELECT * FROM quantifiedIngredients WHERE [i respondsToSelector:@selector(recipe)];

See what I mean? I forget whether CoreData lets you play with some kind of cursor when working with predicates or fetchedThingamabobbers, if it does than I think this is your best bet. Anyway it's Sunday afternoon so that stuff is left as a exercise for the reader.

+1 for a good question.

QED
  • 9,803
  • 7
  • 50
  • 87
  • The problem is that SQL uses the entity-relationship model, where there are no inheritance or many-to-many relationships. So, working at the SQL level makes no sense, as Core Data uses an object model (with inheritance and many-to-many relationships). So, what you say it's like creating a program in C++ and make some modifications in assembler (not so heavy, of course). – Ricardo Jun 25 '12 at 12:09
  • What you say about respondsToSelector is what I'm looking for, it seems there is something call className, but it doesn't work with SQL perstistent store, however it works with others. That's curious. Apart from className or respondsToSelector, what about casting? I sent an email to Apple one week ago and they told me they have to research about this (it's a payed question). – Ricardo Jun 25 '12 at 12:09
  • You don't have the answer, but what you said is very interesting. Thanks a lot. – Ricardo Jun 25 '12 at 12:10
  • I forgot to say your solution with KVO doesn't work. When compiling it says that abstract class doesn't have an attribute in SQL with that name. Thanks for the solution. I already thought about that and tried. – Ricardo Jun 25 '12 at 12:13
  • Well, the SQL was supposed to be interpreted very loosely. Did you create the category against the abstract class? I meant it to be applied to the concrete class which did *not* have a *recipe* property. – QED Jun 25 '12 at 18:07
  • Perhaps you can just fetch all of your objects into a collection and then iterate the collection? Or is that solution too expensive to compute? – QED Jun 25 '12 at 18:08
  • I received a response from Apple technical service. I was told inheritance cannot be used inside a NSPredicate, so the only way (according them) is making 2 different request similar to your suggestion. So, although I don't like this reply from Apple or you, bacause is not the correct way, according to Apple you are right. – Ricardo Jun 26 '12 at 08:41
  • 1
    Ok Ricardo, just don't lose too much sleep! – QED Jun 26 '12 at 14:31