NSFetchedController and sections - ios

I have a Parent Entity Person. It has two Child Entities, Man and Woman.
I want to do a NSFetchedResultsController with them sectioned by the Entity (secion 0 would be Men, section 1 would be Women).
Can I sort them by section based on which Class it is (Man Class vs Women Class? Or do I need to add an attribute stating if its Man or Woman and section by that?

self.entity.name will return the entity name as an NSString. So you could use that. I don't think it's such a great idea to have internal details (the name of an Entity) drive the UI. It's easy enough to declare an attribute for the section name, and then you have full control of the name (including localization).

Related

Model structure when entities having some properties in common

I have 2 entities in Core Data which have some common properties. I have to show both the entities in a same list view. What will be the best practice to do this? Can I do some inheritance thing and put common properties in base class?
Core Data supports inheritance.
Open your core data model and select the child entity. Make sure the utilities pane is displayed (top right button in Xcode) and select "Show the data model inspector" (right most icon in the utilities pane).
Here you can select a parent entity for your entity. All attributes of the parent will be available in the child entity.
Apple documentation on Core Data inheritance
What will be the best practice to do this?
It depends on what type of entities you need to model. For example, if you have a Cat and a Dog, you should move the attributes in common in a base entity (say Animal or whatever you want). In other words, you should have a reason for doing this, i.e. entities have a sort of relationship each others.
Can I do some inheritance thing and put common properties in base class?
Yes of course. In a model you are allowed to have a sort of inheritance pattern like the following.
where
I would stress two things here.
First, you can make base entity as an Abstract Entity. In this way, you are not allowed to create instances of this entity.
As per the doc.
You can specify that an entity is abstract—that is, that you will not
create any instances of that entity. You typically make an entity
abstract if you have a number of entities that all represent
specializations of (inherit from) a common entity which should not
itself be instantiated. For example, in a drawing application you
might have a Graphic entity that defines attributes for x and y
coordinates, color, and drawing bounds. You never, though, instantiate
a Graphic. Concrete sub-entities of Graphic might be Circle, TextArea, and Line.
Second, under the hood Core Data will create a single table with all the attributes you have inserted. So, if you have a lot attributes, you will have a lot of columns for a table.

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 (e.g. 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. (e.g. 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.
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.
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 (As and Bs)
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).

Objective - C Core Data Modeling

I am working with the core data model in Xcode 5 and I am trying to code an app for school that helps me determine my grades. I need the app to show a table view of each class and then when you select one, it takes you to the next page and from there you can add sections (ex. test, quiz, hw, etc.) and be able to add the percent and grade for each.
Now my question is, should I be using 2 entities or just 1? I was thinking two (class and section) and then just use multiple sections per class. But would anyone advise doing this? If so, how should I go about making the class entity the "parent" or the section entity? or maybe there is a way to do it with just one entity and work with multiple sections within it.. Any advice or answers would be appreciated.
Create two entities (Class, Section) and make one to many relationship between class and section. As each class may have multiple section, relationship is the good approach to do this.
class<---------->> Section
Refer this link for relationship sample.
http://www.raywenderlich.com/14742/

Grails how to set _idx field when INSERTing data from outside of the Grails application?

I have a scaffolded Grails application with two domains, Person and Course. Person belongs to Course, and Course hasMany Persons. I have modified show.gsp for Course to list all of the Persons associated with the selected Course.
To achieve this, Course.groovy contains the following line:
List persons = new ArrayList()
And, as a result, the "person" database table contains a persons_idx field. I frequently will be adding new data to the "person" table outside of my Grails application, from an external website.
When INSERTing new data, how to I figure out what to set persons_idx as?
I had originally used a SortedSet instead of an ArrayList for persons, since I care about sorting. But since I am sorting on Person.lastName, and there will always be multiple people with the same last name, then the list will exclude those persons who have the same last names as others. I wish there was another way...
Thanks.
Having two applications manipulate the same Database is a thing to avoid, when possible. Can your 2nd application instead call an action on the controlling app to add a Person to the Course with parameters passed to specify each? That way, only one app is writing to the DB, reducing caching, index, and sequence headaches.
You also state that Person belongsTo Course... so you create a new Person for "Bob Jenkins" for each course that he's in? This seems excessive. You should probably look into a ManyToMany for this.
Without moving to a service, unfortunately, you'd want to change the indices on some if not many of the rows for the children of the Course you're trying to add a Person to, as that index is the sorted index for all the Persons in the Course.
I would suggest going back to a "Set", and do your sorting in the app. Your other question about sorting already told you not to override compareTo to just check the last name. If I were you, I'd forget about overriding compareTo at all (except to check IDs, if you want), and just use the sort() method, passing in a closure that correctly sorts the objects.

Create NSFetchedResultsController managing entities with many to many relationship

I have an entity called Project and another entity called Employee. Employees work on multiple projects.
Project entity has project name.
Employee entity has First name, last name, departmentid number.
I want the data to show up in section header table like this
Project 1
Dept1
-firstname1, lastname1
-firstname2,lastname2
dept 2
firstname3, lastname3
firstname4,lastname4
Project 2
Dept1
-firstname1,lastname1
How can I do this? I don't have to display department names, but it has to be sorted that way.
I am using Core Data & UITableView. I need to construct NSFetchResultsController for this.
I think the root of your question comes from the fact that a to-many relationship results in an NSSet when you access it from the from object of the relationship (ie: Project->Employees - results in an NSSet of employees). NSSets are, of course, unordered.
And the answer is this:
You'll need to sort your employee NSSets by hand. I suggest you convert the NSSet to an NSMutableArray, and then use -sortUsingBlock: or something along those lines to do it. To keep yourself from having to re-sort it every time you need it, store it as a member variable of your Project class. In doing so, it should be pretty easy to create it lazily, and only re-sort it when the dataset changes, which will be better for performance.
You MIGHT be able to do something with a subquery in Core Data... but I think you might find that'll hit the disk more often than you might like. (Just a guess there) The technique I've suggested above is a bit less magical, a bit more brute force, but it'll work, and you'll know exactly how it behaves forever.
Use fetchedResultsController to get your 'Project' entities and you will be able to access and display the Employee NSSet in your tableview datasource methods via their relationships.

Resources