How to save dynamic data into CoreData? - ios

I am downloading data from server which is dynamic.
For example
<Latitude>...</Latitude>
<Longitude>...</Longitude>
<Images>
<ImgUrl>...</ImgUrl>
<ImgUrl>...</ImgUrl>
<ImgUrl>...</ImgUrl>
<ImgUrl>...</ImgUrl>
Here ImgUrl may vary, it can be 2, 3, or 4.
As, Table in CoreData is constant, with pre-defined number of rows. So, how can I achieve my aim?
The one idea in my mind was of appending all of them and save in one row, but I think there might be some other better solutions. So, help is required.
Thanks
How can Make Database field to save it dynamically?

You should make two entities e.g. LocationObject and ImageObject.
Then create one to many relationship: one LocationObject to many ImageObject

This is a simple one-to-many relationship between objects. One object can have many images. An image belongs to only one object.
You model this by creating two entities in XCode: one for images and one for data. You then create a relationship between them. Check the Plural checkbox for "To-Many Relationship", and don't forget to also create an inverse relationship from images back to the data object.

Related

How to save array to an attribute of an entity?

I have a question about core data. I have an Entity named User and this entity has 3 attributes: name, images, videos. How can I save an array of multiple images or videos to the attributes images or videos?
With relational databases, whenever you have one attribute that is going to have a bunch of values for a single entity, you have a one to many relationship and you actually need another entity. So in a strict relational database, you would create a new entity, Image, that had one column pointing to the image's data and a second column pointing to the user that that image is associated with, a foreign key. In CoreData, they represent these foreign key columns as a relationship. So you'll have to make a new entity for each 1-to-M(any) relationship you have and give them a relationship back to user, and in turn user to them.
Try this tutorial, it may help you.

Learning Core Data. Entities, Adding and Loading

So, I'm trying to use Core Data to save instances of a "Screenshot" class, which consist of:
NSString *note;
NSData *screenshot;
NSData *thumbnailOfScreenshot;
NSTimeInterval date;
In my Core Data file, i have two entities because i want to fetch the large images only when necessary, and only 1 at a time (it is to be used in a UITableView).
Entity 1 is called Screenshot and consists of the 4 attributes above, whereas the *screenshot is transient. This entity also has a to one relationship with entity 2(an int called index).
Entity 2 only has 1 attribute which is a Binary data field for the Large images. Also a to one relationship with entity 1.
So, my first question: Is this remotely close to being correct? I'm a little unsure if i even need the Transient attribute "screenshot", in entity 1. And i am also confused if i need to create a new class for entity 2, which seems abit odd, since it will just contain the images.
For now, I'm only trying to add and load instances to and from the DB.
Here is how i (think) i add an instance to the DB, but i am not sure it actually puts it in the DB right away?:
Screenshot *s = [NSEntityDescription insertNewObjectForEntityForName:#"Screenshot" inManagedObjectContext:context];
I am in over my head, so any help will be appreciated. I have read several guides, but none was targeting something similar to this.
Transient properties are not saved to Core Data (they are neither retrieved nor saved out from the backing store). They are most often useful for calculating some sort of property based on stored properties (e.g. I use them for queries based on the first letter of a person's last name -- I'm storing the full last name, but the firstLetterOfLastName is a transient property -- but one that I can order results on since Core Data knows about it).
If I'm understanding your model correctly, you likely want no transient properties at all.
I also don't think you need an entirely new model for your "large images". You can instruct Core Data to optimize it's backing store for large binary attributes by turning on "Store in External Record File". You'll find this in the Data Model Inspector pane underneath where Transient and Optional are set. This will keep the actual backing DB snappy, but allow Core Data to retrieve these large binary attributes and you may still work with them seemlessly with a Core Data NSManagedObject instance.
Also, in general, do not relate items by an "index" value of some other stored Core Data object. There's plenty of reasons to do so, but in general, this is what Core Data relationships are for. If "Movie" has multiple "Screenshots", for e.g, you would have a relationship on a Movie instance called "screenshots" that you simply add each screenshot to (it's effectively an NSMutableSet as far as you care).
Core Data is an object graph, not a relational database. If you add the same object instance to two relationships on different owner-object instances, you aren't duplicating the child-object -- Core Data does all the work to interrelate them for you (assuming your models are setup in a good way).
I'd rethink this. I think a single entity is enough for this. I'd either add a BOOL value named 'large' and do a fetch when "large = NO" to get the small images. Alternatively, if you want more control, add a 'pixels' or 'megapixels' field which describes the size of the image. Then you can fetch where 'pixels > 3000000' for instance.
If you have a special relationship between two images (i.e. one image is a thumbnail of another), I'd just add a relationship to another Screenshot entity.
Alternatively, you could also make one Entity the "Parent Entity" of the other (see the Data Model inspector when you have an entity selected).
You're on the right track. Keep thinking about how you want to use your entities. This should help you describe the relationships better. Quite often I write the code that uses the entities before I define them in a data model. This lets me end up with cleaner interfaces and less overlap between entities.

iOS retrieving and ordering Core Data entities with relationships

I recently asked this question about how best to retrieve and display in a tableview the titles my FRC is using for section headers.
Following a line of research suggested by #Mike Pollard in the second answer to my question, I ran across this question and was immediately struck by the similarity to my situation, and by the 4th answer, posted by #aroth.
Aroth's approach certainly appears sound, and I've created a new Category entity. Specifically, Category has a to-many relationship with Item, and Item has a to-one relationship with Category. However I'm having trouble understanding one aspect implicit in his proposed solution, and, more fundamentally, in this relationship:
In my case, both Category(s) and Item(s)--"Item" is called "ListActivity" in my case, but "Item" will do for illustration purposes-- will be named via two corresponding user input fields, which seems like it could result in multiple entries of the same name in the Category list.
My question:
How can I ensure that when I fetch a list of Categories that I get a singular instance of each category, i.e., one category per row in the tableview, with no repeats? Will Core Data automatically assign each new incoming Item to a singular instance of the appropriate Category via the relationship? Or will it somehow test for and winnow the list down to one entry per Category name upon receiving the fetch request? Or must the filtering be done with a predicate in the fetch request?
Thanks!
Core Data will do what you tell it to. This sounds like an issue related to you creating content in your data store rather than an issue with the FRC and table view. It's your responsibility to search for and reuse existing objects rather than creating duplicates and adding them to the store - indeed, only you (your code) knows what constitutes a duplicate.
So, basically, as you create new items, use a fetch request and predicate to find the suitable existing category (or suggest categories based on partially entered names). Then, either connect to the existing category or create a new one.

Core Data Model

I'm struggling with creating a suitable Core Data model for my app. I'm hoping someone here can provide some guidance.
I have two entities -- "Goals" and "Items". The Goals entity contains only a goal description, but any goal may have any number of subgoals, and these may extend multiple levels in a tree structure. Subgoals are to be contained within the same entity, so presumably the Goal entity will contain a pointer to "parent" which will be the parent goal of any subgoal.
There will also be an "Items" entity that contains a couple of text fields and a couple of binary items, and must be linked (ideally, by a unique identifier, perhaps objectID) to the particular goal or subgoal the item(s) are related to.
I am totally fumbling with how to set this model up. I know what attributes need to be in each entity, but the relationships, particularly between goals and "subgoals", has me stumped. I don't seem to be able to turn up any good examples of tree structures in Core Data on the Internet, and even the couple of books I have on Core Data don't seem to address it.
Can anyone here help an old SQL programmer get headed the right direction with these relationships in Core Data? Thanks.
Have you tried creating a one-to-many from Goal to itself, and a one-to-one from Goal to Item? The only thing I would worry about here is circular references.
Also, read Relationships and Fetched Properties in the CoreData Programming Guide.
Here is how it is done:
You set up a to-many relationship from Goal to Item in the model editor. Don't use any ids, foreign keys etc. This is old-fashioned database thinking - you can forget about it. Here we are only dealing with an object graph. The database layer is just an implementation detail for persisting the data.
Make two more relationships in entity Goal to itself: a to-one called parent, a to-many called subGoals. Make them the inverse of each other. Simple!
QED is correct, you can create a to many relationship on goal (call it subgoals) as well as a to-one relationship on goal (call it parentGoal) and set them as inverses to each other.
Then create another to many relationship (call it items) on the goal entity, with the inverse being a to one relationship on the item entity (call it goal). Then you're all set. You don't need to link items with a unique id, just add them to the items relationship.
Also note that if you did want to give items a unique id, do not use the objectID. The objectID should only be used as a temporary id as they are not guaranteed to remain the same. In fact they will change if you ever do a Core Data migration.
One way, though not really great, is to create a another entity, say subGoal, and each goal has one subGoal and each object of subGoal has many goal.

How to store many item flags in core data

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.

Resources