简体   繁体   中英

Performing the equivalent of a union with Core Data for a UITableViewController

I know union is a SQL construct, but it's the best analogue for what I'm trying to do.

I have multiple groups of data that I'm receiving from an external source. I'm maintaining them as separate entities in Core Data (they only have some attributes in common (eg name)), but I want to present them in the same tableView .

Say I have an entity Food that has relationships with FruitGroup and VegetableGroup. The FruitGroup has a relationship with Fruit which has a relationship with FruitType. The VegetableGroup is similar.

How can I use FruitGroup.Fruit.name and VegetableGroup.Vegetable.name as sectionTitles? And FruitGroup.Fruit.FruitType.name and VegetableGroup.Vegetable.VegetableType.name for row data. (I tried coming up with a predicate that walks down from Food, but that doesn't appear to be workable)

Example modeled data (my groups are far more disparate than fruits and veggies, so re-doing my data model is not an option):

Food
  FruitGroup
     Apple
         Macintosh
         Granny Smith
     Pear
         Bartlett
         Asian
         Anjou
  VegetableGroup
     Asparagus
         white
         wild
     Peas
         baby
         split

Which I would like to appear as:

Apple [section]
   Macintosh   [row]
   Granny Smith
Pear
   Bartlett
   Asian
   Anjou
Asparagus
   white
   wild
Peas
   baby
   split

I could use multiple NSFetchedResultsControllers in the UITableViewController and conditionally select the FRC within each of the UITableViewDataSource methods, but that doesn't feel clean.

I'm thinking about subclassing NSFetchedResultsController and, internal to my subclass, merging the results of multiple private NSFetchedResultsControllers that each represent one of the entities. (eg sections returns a concatenation of the returns from the sections calls of the internal FRCs)

Does this make sense - or is there a better way? (I saw Core Data Union Query Equivalent but since there are relationships among my entities, I wanted to seek alternatives)

While you can do this as described in the other answers (via creating an abstract Parent entity), I would not recommend it. The performance when it comes to dealing with abstract parents gets bad very quickly. The reason for this is that Core Data will put all of the children into a single table in the underlying SQLite file.

I would suggest going a different route. Have a single entity called Food with attributes describing if it is a vegetable or fruit. Then you have one NSFetchedResultsController which has the type of the food item as the sectionPath and you will get your display the way that you want it.

I recommend creating entities in Core Data based on what the objects are as a very loose level. I would not create entities for Honda, Ford and Dodge, but create an entity for Car and perhaps type or a relationship to a manufacturer.

While Core Data can be backed by a database, at the end of the day it is not a database but an object graph and should be treated as such. Trying to normalize the database will result in poor performance of the object graph.

To answer your question:
You cannot unify different entity types (if they are not subclasses of the same entity) under a single fetch request. You can define an entity ( B ) to inherit from another entity ( A ) and then fetch by the parent entity ( A ) and get both kind of entities ( A s and B s)

You can try and think of it this way:

Item ("Macintosh","White Asparagus",...) has a relationship to Group ("Apple","Asparagus",...), and Group has a relationship to Area (or simply to another parent group).

In this manner you could use a single FRC with sectionNameKeyPath of "group.name" and entity Item (you can filter by "group.area" to only select food items).

You should probably look into abstract entities. For example, you could create an abstract entity called Food . Then you're able to create Fruit and Vegetables , which inherits the abstract entity. You'll have to set Food as the "Parent Entity".

Then you could fetch all the items with the entity Food , which includes both Fruit and Vegetables . Based on your post, you'll probably will have a relation from Food to FoodGroup .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM