CoreData Guidance - iphone

So I have this problem I am trying to solve - I wonder if anyone can comment on/help me with the approach. The thing is, I have it partly solved, but with the rest I'm not quite sure.
Here's the deal:
I have a fairly large DB online which I want to load on first start of the App. After that I am only going to load it if new versions exist.
I use an xml parser to parse the data and enter all the data to my data model. The database consists of thousands of products, all described by various attributes.
Anyway, it's easy for me to save thousands of products in a database, then retrieving the data on demand.
I have a problem of how to categorize them and how to save the category data. There is a main category i.e. Hi-Fi which has several subcategories- let's say 'stereo', 'tuner', 'phone' and so on....
How to best save this info, that category a has 15 subcategories and each of these categories in turn has 30 products while securing performance and keeping process-time at a minimum. I don't want to check all 2000 Products whether I need to show them in a certain table view each time I open a new table view.
Any hints on the apporach are appreciated.

You'll need two entities: Product and Category.
Category has a to-many relationship called subcategories with a target entity of Category. The inverse relationship can be called parentCategory. Category also has a to-many relationship called products. Product would have an inverse relationship called category (or categories if a product can belong to multiple categories)
Now, you can get all the products for a given category by checking its products property. If you want to include all the products in the subcategories, you can do a fetch request with a predicate like this:
[NSPredicate predicateWithFormat:#"category == %# OR category IN %#", category, category.subcategories];

I think you can solve it by having a Core Data modal consisting of three entities: Product, Category and SubCategory.
Product has a relationship category with destination Category and a relationship subcategory with destination SubCategory.
Category has a to-many relationship products with destination Product and a to-many relationship subcategories with destination SubCategory.
SubCategory has a to-many relationship products with destination Product and a relationship category with destination Category.
When defining these relationships remember to assign the Inverse relationships as well.
Now you get a list of all products belonging to a specific category by just loading the Category in question and accessing the products property. It should also be possible to use NSFetchRequest for Product with a predicate specifying which category you want. Which is best regarding performance and memory requirements I can't say so you just have to test which approach works best.

Related

how to create a many to many relationships with core data? Swift, xcode

I have 2 entities.
entity 1 - People
entity 2 - books
People entity has a property which is an array of string names of their favorite books.
I need to create a relationship that somehow maps the favorite book of a person to the corresponding book entity object(s).
I am not sure how to do this.
So far I have started by creating a relationship in core data model for people by setting destination to "books" and then for the books entity creating a relationship by setting destination to "people".
I don't see or understand how this will automatically pick out each of the person's favorite books...at the end of the day they are both seperate objects. How will the people class know that for a specific people instance that this, this and this book are that person's favorite?
Person attribute as array of string names of books -- very bad idea!
You need a to-many relationship with the Book entity. That's it.
Person <------------>> Book
Then, to get an array of book titles for a particular person:
(person.books as! Set<Book>).map { $0.title }
The person can have an additional to-one relationship (e.g. called favoriteBook) to one of the books.

Core data cross referencing two relationships

I have a data structure in Core Data like so...
User
Item
Category
User has a toMany relationship "FavouriteItems" to the Item entity.
Category also has a toMany relationship "Items" to the Item entity.
The user can select favourite items from any categories they wish. At the moment I am listing all the items and then displaying the Category alongside.
What I'd like to do is display all the user's favouriteItems for a selected Category.
i.e. select all the Items that have a relationship with Category x and User y.
I'm currently doing this by getting all the Items through one relationship (i.e. User.favouriteItems) and then filtering the NSSet using a block predicate.
Is it possible though to do this with a simple CoreData predicate?
Hmm... thinking about it would a predicate like this work...
[NSPredicate predicateWithFormat:#"interestedUser.id = %# AND category.id = %#", user.id, category.id];
And then run a fetch request on the item entity?
Would that work?
Shooting pretty blind as that's an awkward scenario to set up just to answer a question but perhaps
If you are filtering an array of Items which has the correct inverse relationships set up.
[NSPredicate predicateWithFormat:#"%# IN interestedUsers AND %# IN categories",
someUser,
someCategory];
Basically the Item has many users (interestedUsers) so we are saying is our user in this collection.
Similarly the Item has many categories (categories) so we are saying AND is our chosen category in this collection.

CoreData Relationship between entities and attributes

I'm having a little trouble grasping CoreData relationships, i'm note sure which relationship type I should be using between my 2 entities or if my logic is correct.
1) "Person" Entity - attributes such as name, tel, address, country, etc...
2) "CountryList" - attributes such as countryName, countryLat, countryLong, etc..
The CountryList entity is pre populated on first run of the app to include all the countries in the world and their respected data.
Where i'm stuck is do I need a relationship between these two entities?
I will be allowing the user to select a country from the CountryList entity data and wish to store there selection in the country attribute for Person entity.
Do I just take the countryName from CountryList as a string and store it in country from Person? or can I make a relationship between them?
I know a user can only belong to 1 country but a country can have lots of users so is this a one to many relationship? Or is it many to many because lots of users can belong to a country but a country can have loads of users? Confused!
Could someone please enlighten me on this and point me in the right direction in what i should be doing in xcode.
Many Thanks in Advance
Matt
EDIT: Is this correct?
I have made the changes to Entity names etc and think I now have the relationship set correctly.
EDIT 2: Removed country attribute and renamed relationships
Firstly, your "CountryList" entity should be called "Country", since it represents only one country. The fact that you have many of those countries has nothing to do with its name.
After that, it seems just natural to use a relationship, one "Person" has one "Country", but one country can have many persons. Therefore, one-to-many relationship. Using a relationship will simplify many operations you might want to perform (i.e. access all the country information of one person, or get a list of all persons being in one particular country).
Oh, and this might help you understand relationships a bit better: There are no "many-to-many" relationships in CoreData per se. You always define a relation from a source to a target. So if you define a relation from Country to Person, this will be a one-to-many relationship. One country, many persons. You can then define a relationship from Person to Country, which would be a one-to-one relationship. One person, one country. If you defined this as an one-to-many relationship, you would end up with a de facto many-to-many relationship (because on person can have many countries and one country can have many persons). It's not as complex as it appears.
Now, after you've defined your two relationships, you can set them as each others "Inverse Relationship". Do it for one of the relationships, the other one will be set automatically. After you did that, CoreData will for example update a Person's country when you add the person to the country's list.
See https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdRelationships.html for further information.
CountryList should just be Country
Then you set a 'many to one' relationship between Person.county and Country
You are using Core Data so you must define relationship between Person and Country if you want to fetch person's country from database.
And in this relationship you may take one to one relationship. As One person will belong to one country only. Of Course a country will have many person but unless you want to show all people related to particular country you do not need one to many relationship..
In case you want to implement one to many relationship this tutorial link maybe helpful to you for understanding one to many relationship..
http://www.theappcodeblog.com/2011/09/29/iphone-app-development-tutorial-core-data-part-2-one-to-many-relationship/

Core Data - Getting Unique Rows

I'm working on an iPhone app that uses Core Data. I have only one entity called Books, and that entity has the attributes Title, Author, ISBN, Description and Shelf.
I'm working on the book editing view, and want to have a UIPickerView listing all of the unique Shelf rows so that the user can just pick a shelf.
My question is -- how do I get an NSArray of all of the unique Shelf attributes across all of the books in the database? I have access to the managedObjectContext of the Book being edited, so would I use some sort of a fetch request?
Thanks!
You can get a duplicate-less array of available shelves with the array operator #distinctUnionOfArrays.
But IMO it would be a cleaner solution to redesign your data model, so that there are two entities (books and shelves).
You could then create a relationship between book and shelf.

core data iphone readonly relation

I have situation where I dont want to add records to the relation table.
For example :
I have "TRIPS" entity and it has attribute for "LOCATION_ID", I am filling it when user creates a new TRIP and select a LOCATION from the LOCATIONS entity
In "LOCATIONS" entity I am allowing user to create locations and I am assigning a unique ID to each location.data will not be repeated here.
Is there any way to link the LOCATION_ID into LOCATIONS entity ,so when ever I access a trip(NSManagedObject) it automatically get LOCATIONS entity record (Object) ?
I mean automatically (Manually I can do that)
Thanks,
Raghu
If I understand correctly your question, you simply need to model differently your entities in the Core Data model, as follows. In your TRIPS entity, add LOCATIONS as a relationship, not as a property as you currently do. The relationship may either be to-one or to-many from TRIPS to LOCATIONS, depending on the constraints you want to enforce in your application, and to-one from LOCATIONS to TRIPS.
Once you do this, when you fetch objects from the TRIPS entity, they will also contain a LOCATIONS object (if you decide to use a to-one relationships) or a set of LOCATIONS objects (if you decide for the to-many relationship).