How to fetch a Restaurant by its menuId? - iphone

I have set up Core data in my application, with two entities: Restaurant and Menu. There are about 30 or so restaurants, and 6 menus. One menu can belong to several restaurants.
However, each Restaurant entity has a menuId field. Is there a way to retrieve the specific menu entity according to which menuId the Restaurant entity has?
I also have a problem with values being stored more than once, even though they are the same. How can I prevent that from happening?
I'm pretty new to Core data, so any best-practice tips would be appreciated!
Thanks!

You could use an NSFetchRequest to retrieve menus by their id, but it would actually be better to define a relationship from your Restaurant entity to your Menu entity (and vice-versa). Internally, that does pretty much the same thing as your menu id attribute, but it's much more convenient to use.

You're following a database approach, based on tables and IDs to link these tables. This is wrong in Core Data, you must follow a object graph approach and CoreData will transform it to a corresponding SQlite database in a manner completely transparent to you.
So given the entities °Restaurant" and "Menu" you will create:
- in the entity "Restaurant" a 1-to-many relationship to "Menu" called "menus"
- in the entity "Menu" a 1-to-many relationship to "Restaurant" called "restaurants"
You will just need to add each restaurant menu to the NSSet corresponding to the menus relationship for a given menu, and vice versa. As you can see in this way you don't need to care about IDs, but just the object relationships.
As far as repeated data, this depends on you. Normally you should have a way to identify the unicity of an object (e.g.: the menu name, the restaurant name) and then try to retrieve it from Core Data before adding it as a new object.

Related

Delete nsmanagedboject from context with many to many relationship core data iOS

My model have 2 Entity (Category and News) with many to many relationship: (It mean a category may have many news and a news article may belong to one or more Category).
Below is my design:
Entity 1:
Category (attributes: categoryID, title, show, position) and a relationship with News Entity called "news".
"news" relationship has destination is "News", inverse relationship is "categories", type to-many relationship and delete rule is cascade.
Entity 2:
News (attributes: newsID, quote, content, link) and a relationship with Category Entity called "categories".
"categories" Relationship has destination is "Category", inverse relationship is "news", type to-many relationship and delete rule is nullify.
Object graph look like this:
News <<-------------->> Category
My question is:
1> Is my designed model is good ?
2> Arcoding to my designed model, if I delete a News object from it context example like:
id newsObjectToDelete = ....
[managedObjectContext deleteObject:newsObjectToDelete];
Does Category object that newsObjectToDelete belong to automatically remove newsObjectToDelete from NSSet of relationship "News".
3> If I want to constraints that a "News" must belong to at least one "Category". How to implement that constraints
Thank in advance. Sorry for poor English
It's tough to say whether or not this is a good fit for your app, but it looks like a pretty standard relationship.
If you delete an object, it is automatically removed from all Core Data relationships. Don't worry about a dangling reference to some deleted object, Core Data handles that for you.
Core Data can really only generate an error (and blocking the save) or take some automatic action during the save. You can do either of the following:
In Your Data Model: Using the data model editor, uncheck "Optional" for this relationship, and/or set the "Minimum" count to 1:
In Your "News" Subclass: If you need more fine-grained control and/or error reporting, you can check this during validation (to generate an error) or maybe take some automatic actions during the save process.
Note that using validation (either in the model or in your code) is only going to help during the development and debugging processes - calling -save: on the managed object context will fail, returning NO and generating an error. This should be a last resort, and really just there to keep bad data from getting into your persistent store. A validation failure like this tells you that some other part of your code is wrong and generating bad objects.

Modeling a to-many relationship in Core Data

I asked this question earlier, but I'm missing one important thing. I have a NoteObject entity and every note, without Core Data, just has an arrayOfTags (which is an array of NSStrings). I decided to use to-many relationships to store the tags instead of an array. So I created a new "Tags" entity, and set up a to-many relationship from my NoteObject to Tags. This works great when every tag is related to only one note, but I'm unsure how I would go about linking one tag with multiple notes. How would I set up that relationship?
In you data modeler just make the Tags -> Notes relationship a to-many relationship. If you have already generated the Entity subclasses you will have to redo those. You will also have to be careful when creating tags to ensure uniqueness, but other than that it should be fairly straightforward. myTag.notes should work just as well as myNote.tags.

fetchedresultscontroller with two entities - predicate to target each entity?

My iPhone app has a summary page (UITableView) where I would like to show a quick overview and therefore I need to get info from several entities. It was suggested to create an abstract parent entity and have my two entities as children of this one. This do allow me to fetch the two entities using the one fetchedresultscontroller.
This works but I find that I need to filter the return a small bit. Because of the 'hack' above these entities have nothing in common so I need completely separate predicates.so from EntityA I would need "color = blue" and from EntityB "length >= 10". Because the entity I'm actually querying have none of these this doesn't work at all.
Is there a way to do this or what's the best approach here?
Niether the UITableView or the NSFetchedResultsController is designed to deal with more than one entity at a time. Moreover, it seldom makes any sense to try to do so. If you find yourself in such a situation, you probably need to rethink your data model design.
If entities are logically associated with each other then they should be linked by a relationship. If data from any two objects is to be displayed in the same tableviewCell without being gibberish then they must have some logical association and therefore should be linked by a relationship of some kind. To display in the table, you fetch one side of the relationship and then walk the relationship/s to find the other related objects.
If the logical association is strong, it should be defined as a formal relationship in the data model e.g.:
EntityA{
//... some attributes
b<-->B.a
}
EntityB{
//...some attributes
a<-->A.b
}
However, if the relationship is weak or transient, then you should use a fetched property to relate them. The fetched property dynamically searches for other entities based on a preprogrammed fetch.
EntityA{
creationDate:date
someBs--(creationDate=$FETCH_SOURCE.creationDate)-->B
}
EntityB{
creationDate:date
}
A key concept here is that Core Data is providing the entire model layer of your Model-View-Controller design. It is not just a dumb database but an active object graph that models both the data itself and its behavior. Once you have a properly designed data model, problems with the controllers and views resolve themselves automatically.
If i understand correctly, you can use notifications and send a dictionary of required information to the UITableView view controller class.

Core Data - save existing managed object and show it in an another view

I'm working on an table drill-down style iPhone app that has prepopulated data. I use Core Data and NSFetchedResultsController to populate the table views. In the last level of the table view which shows an item (managed object) I want my user to be able to select that item which should eventualy be shown in another view. That other view would be a kind of a favorite list (implemented in a tab view). The user would then have a choice of deleting or adding other items to the favorite list.
My model has three entities each representing one level of table view. Higher level entity has a to-many relationship to lower level entity and inverse relationships are to-one
How do I use the existing managed object (object in the last level of table view) to save it and show it in favorite list view? Should I create new entity and establish relationship between the two?
My model has three entities each
representing one level of table view.
That is thinking backwards. What you have is three entities that exist logically in a hierarchy and the hierarchy of views reflects that logical structure. The views exist to display the data, the data does not exist to display the views. It's an important concept to grasp and if you fail to do so, your application design will always be overly complex, fragile and hard to extend and maintain. The data model always comes first and the logical relationships within the data model itself and the users interactions with that data ultimately control the UI structure of the app.
It's an easy trap to fall into because the instructional materials always start with the interface first. However, in real app design, you start with the data model first and work forward to the interface.
In this case, if you want to store favorites of some entity you have two choices. If the entity being a favorite is part of the core relationship between data and the user and you only have one set of favorites, then you could legitimately add a boolean "isFavorite" attribute to the entity and then just fetch al the entities where "isFavorite==YES"; If you have multiple list of favorites then the best method would to to create a FavoritesList entity and then relate each favorites entity to the objects it is supposed to list.
If the favorites are a minor and peripheral part of the user's interaction with the data you could store the objectIDs in the user defaults.
Yes, you could create a new entity and store the relationship. It's not necessarily the only way to do it -- you could store pointers to your NSManagedObjects in a container like an NSMutableArray -- but if you want to remember that list for later (i.e. save it between launches), it might make the most sense to also store it using Core Data.

Set a relationship with Core Data

I have two entities that are connected through a one-to-many relationship, let's say CategoryEntity and ItemEntity. The relationship is optional for CategoryEntity (there can be categories without items), but required for every ItemEntity. At the app's loading, the Categories already exist in the store, and I want to import ItemEntities and connect them to the appropriate CategoryEntity.
Obviously executing a FetchRequest for each ItemEntity to find the matching category wouldn't be a good solution because there will be about 4000-6000 Items each time..
So, is there something more efficient I could do?
If you have correctly setup your Core Data model, then you have a to-many relationship from the Category entity to the Item entity, and an inverse to-one relationship from Item to Category. Also, you have a "cascade" delete rule for the to-many relationship and a "nullify" delete rule for the to-one relationship.
Assuming this, each time you insert an Item object, setting its Category relationship automatically inserts the Item into the corresponding Category. Deleting an Item automatically removes it from the corresponding Category.
On the Category side, removing a Category automatically removes all of the corresponding Item objects.
Therefore, when you fetch Items, you have already fetched for each Item object its corresponding Category object. You do not need do anything else. Note that, by default, you are not actually retrieving the Category object during the fetch: instead a fault is fired the first time you try to access the object and the object is retrieved at that time. This provides better performances if you do not plan to use immediately the Category object stored within the Item object just fetched. If you plan to use the Category object almost every time you fetch an Item, then you must use the NSFetchRequest methods
- (void)setReturnsObjectsAsFaults:(BOOL)yesNo
- (void)setRelationshipKeyPathsForPrefetching:(NSArray *)keys
to tell Core Data that you do now want faults and that you ask for prefetching your Category relationship.
When you say 'import' item entities, what do you mean? Are these in another Core Data store, defined in another format in a file somewhere, retrieved over the network?
One approach would be to fetch all the categories in one go and add them to an NSDictionary acting as a cache and keyed by some identifying value that allows you to perform a quick lookup. For each item entity that you instantiate during import (whatever that means), retrieve its category ID and then retrieve the Category MO from the cache. Set the relationship and then save. Even better, batch up a number of insertions and save every 10, 100 or 1000 to reduce IO overhead.