I've got a table with attributes:
Country, Place, Description etc.
A value of the country attribute can be repeated(one country can repeat two times or more).
I need to get from this DB:
All Countries. (for tableView)
All Places for a particular Country.(for tableView)
Other info for a particular Place. (for details
view)
So, the question is what's the best way to implement the xcdatamodeld.
My thoughts:
I can create just an simple Entity without any relationships. But to
get 1 and 2 points(described below) I have to go through all
ManagedObjects and I thinks it's not thes best way.
To use setPropertiesToFetch:. I think it's a good way but I'm not sure is
it okay to leave my database so simple without any relationships
like(Country -> Place)
I thought to create three entities Country,
Places, Details. And load necessary data from different entities.
But it's my first experience with CoreData and I'm not sure does it
make sense or no?
P.S. This is simple example. Real database can be much more bigger and complicated.
The example is trivial you could start with something as simple as:
This is how you would model it if you was ignoring the database - luckily CoreData will take care of the persistence for you and you can just use your models without thinking too much about tables
You have a concern about the efficiency once you click on a country. You should use an NSFetchedResultsController to handle efficiently batching data into the UI and working with a tableView. You would simply set up the NSFetchedResultsController to use a predicate something like:
[NSPredicate predicateWithFormat:#"country == %#", self.selectedCountry];
Side note:
You should always profile to see if there is a real problem rather than working on opinion of estimation
Related
I'm making an iOS app with thousands of flash cards with questions. The questions pool has about 10,000 questions, and is divided in 5 categories. One single question can have only one category. Categories won't change, they are fixed. Questions are just text. No images involved.
I was thinking about two approaches:
1) Create an Entity for the question with a category field (int) in it.
Fetch the results to get only the questions of a specific category.
2) Create 5 Entities, all with the same fields, except for the category, which has a default value corresponding with the category.
Why option 2?
I think option 1) is the clean proper one, but the app has so many questions that I'm thinking that submitting a query filtering a specific field, is maybe slower than retrieving a completely different Entity. I'm thinking from an SQL point of view, where maybe performing a SELECT on one table and then another one, should be faster than a SELECT...WHERE on the same table?
I agree with you, option 1 is the clean proper one. Retrieving the category from another entity will add minimal overhead. Moreover, if you have to edit a category you have only one entry to change. You can also add other categories more easily.
If you are really concerned about performance (and I don't think you should at that point) you can code both and do a speed test. But that is really overkill and the difference will probably be insignificant.
I do have some JSON file http://jsonblob.com/530664b3e4b0237f7f82bdfa I am pulling from forecast.io.
I am little confused how I should be creating my CoreData entities and relationships.
In below setup, I made my Location entity as the parent entity and created a separate entity for Currently, Minutely, Hourly, Daily. However I have decided it's best to hold all the information regarding the weather data in one entity, so I created a Data table for that purpose and tied it to Daily and Currently in the image below.
Before going further, I paused and would like to get a second opinion on it. Is this a valid way of going forward with this?
EDIT: Based on Wain's response I changed my model to this
Currently Minutely and Hourly add little value as they don't have any attributes or relationships. It's also generally easier to add a type attribute rather than having a number of sub entities because you can easily filter the type using a predicate while doing a fetch. If you're going to add more in the future then there could be a case for keeping sub entities.
Once the entities are trimmed down then you only have a Location and Data with a relationship. You should make that relationship bi-directional so that Core Data can manage the data store contents better. (this applies to all relationships, even if you keep the sub entities you already have).
Other than that, fine :-)
I'm using Parse (www.parse.com) for the backend database for an iPhone app. I'm creating a fitness application and want advice as the best way to structure the classes and relationships.
A few needs for the database:
1)Sets(have attribute or weight and reps)
2)Exercise (a single instance of an Exercise which can contain multiple Sets)
3)Workout (which will be a single instance for a particular workout which will represent 1 single day. No single day can have 2 Workout objects. Can contain multiple Exercise objects.
Then I also need some classes for Routine which is independent from the ones above.
4) Routine can contain ExercseForRoutine objects (which will look the same as Exercise but will just be used for routines, will not be able to add sets to.
5) ExercseForRoutine will be added to Routine, but not related to the actual Exercise objects that will be used when the user enters workout data, this object is just used to create a Routine.
Any advice on tips and how to structure this using Parse would be appreciated
Don't get too hung up on your object model or your data store. If you haven't done so already, generate a list of core use cases and use those to drive your object model. But assume that you will iterate on it until you find a good fit with your domain. The one thing that sounds like it might be a bit fishy about your spec is writing the single day constraint into your Workout class. That doesn't sound like it's essential to the domain and probably will be awkward to code (e.g., what happens if I start my workout at 11:55pm?).
I am trying to do the following in my iPad app. I have a structure that allows people to create grouped lists which we call "Templates". So The top level CoreOffer(has Title) which can have many groups(has grouptitle/displayorder) which can have many items(has ItemTitle, DisplayOrder). As shown below. This works great, I can create Templates perfectly.
Image link
http://img405.imageshack.us/img405/9145/screenshot20110610at132.png
But once Templates are created people than can use them to map against the Template which I will call an Evaluation. A Template can be used many times. The Evaluation will contain a date(system generated) and which items from this particular Template have been selected.
Example below, people will be able to check particular rows in the screen below, this is then an Evaluation.
Image link
http://img41.imageshack.us/img41/8049/screenshot20110610at133.png
I am struggling to figure out how to create and store this information in the core data model without duplicating the Template. (struggling coming from a SQL background!) In SQL this would involve something like an evaluation table recording each itemid and its selection status.
I expect its quite simple but I just cant get my head around it!
Thanks
The first thing you want to do is clean up the naming in your data model. Remember, you are dealing with unique objects here and not the names of tables, columns, rows, joins etc in SQL. So, you don't need to prefix everything with "Core" (unless you have multiple kinds of Offer, Group and Item entities.)
Names of entities start with uppercase letters, names of attributes and relationships with lower case. All entity names are singular because the modeling of the entity does not depend on how many instances of the entity there will be or what kind of relationships it will have. To-one relationship names should be singular and to-many plural. These conventions make the code easy to read and convey information about the data model without having to see the actual graphic.
So, we could clean up your existing model like:
Offer{
id:string
title:string
groups<-->>Group.offer
}
Group{
title:string
displayOrder:number
offer<<-->Offer.groups
items<-->>Item.group
}
Item{
title:string
displayOrder:number
isSelected:Bool
group<<-->Group.items
}
Now if you read a keypath in code that goes AnOfferObj.groups.items you can instantly tell you are traversing two to-many relationships without knowing anything else about the data model.
I am unclear exactly what you want your "Evaluations" to "copy". You appear to either want them to "copy" the entire graph of any Offer or you want them "copy" a set of Item objects.
In either case, the solution is to create an Evaluation entity that can form a relationship with either Offer or Item.
In the first case it would look like:
Evaluation{
title:string
offer<<-->Offer.evaluations
}
Offer{
id:string
title:string
groups<-->>Group.offer
evaluations<-->>Evaluation.offer
}
... and in the second case:
Evaluation{
title:string
items<<-->>Item.evaluations
}
Item{
title:string
displayOrder:number
isSelected:Bool
group<<-->Group.items
evaluations<<-->>Evaluation.items
}
Note that in neither case are you duplicating or copying anything. You are just creating a reference to an existing group of objects. In the first case, you would find all the related Item objects for a particular Evaluation object by walking a keypath of offer.groups.items. In the second case, you would walk just the keypath of the items relationship of the Evaluation object with items.
Note that how you ultimately display all this in the UI is independent of the data model. Once you have the objects in hand, you can sort or otherwise arrange them as you need to based on the needs of view currently in use.
Some parting advice: Core Data is not SQL. Entities are not tables. Objects are not rows. Attributes are not columns. Relationships are not joins. Core Data is an object graph management system that may or may not persist the object graph and may or may not use SQL far behind the scenes to do so. Trying to think of Core Data in SQL terms will cause you to completely misunderstand Core Data and result in much grief and wasted time.
Basically, forget everything you know about SQL. That knowledge won't help you understand Core Data and will actively impede your understanding of it.
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.