I'm picking an image from gallery and converting it to NSData. Later on I'm storing it in CoreData and retrieving later. But if I pick 2 images from the gallery, I want to store the `NSData info of both of them to an array and store that array to CoreData. But how an array can be saved to CoreData that I'm not able to figure out. Did go through other SO posts dealing with similar issue but they weren't of much help.
Also please note..I cannot store the array to Userdefaults or Document directory in this scenario because there are other data associated with the image like name,qty etc. and they are all stored in coredata and they should later be displayed in tableview. If just the images are stored using some other method and the other details stored using core-data, there won't be proper data populated in the tableview..
Use entity as ImagesArray with relationship to many entities as Image. In its turn, the picture will have properties e.g. imageData (Binary Data), Name (String) etc. and relationship to one ImagesArray.
See example
Create ImagesArray entity with identifier or other properties for identification.
And then create Image entity with properties imageData (Binary Data), name (String) etc.
Entity ImagesArray will have relationship images to many entities Image.
Entity Image will have inverse relationship imagesArray to one entity ImagesArray
In code you will create set of entities Image with imageData, name etc.
Then create ImagesArray.
Add set of entities Image to ImagesArray's property (relationship) images.
Entity ImagesArray will have set of entities Image.
In my opinion saving an image to CoreData is not a correct approach to save images. You should save them in the app sand box and then store in CoreData the path.
Saying that you can save an Array by using NSValueTransformer, you can find an example here. but probably the best approach is to create a relation between a User entity and Image entity One-to-Many.
Related
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.
I am working on a project where the user would be able to save an image, with a caption and title, and then have it saved using Core Data. The issue I am having is trying to add an album, where users could keep similar images, with captions. I am new to CoreData and have spent all day viewing documentation and combing through Stackoverflow.
I have attached an image (certainly not an artist) of the basic layout I am looking for.Layout
I have also attached an image of what I believe the data structure would look like. Data Structure
The parts tabbed with red are the issues I am having structuring. I have already structured what I believe would be the 'Top' layer of the data structure.
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context: NSManagedObjectContext = appDel.managedObjectContext
let saveData = NSEntityDescription.insertNewObjectForEntityForName("ScannedItem", inManagedObjectContext: context)
let imageRep = UIImagePNGRepresentation(image)!
saveData.setValue(textTitle, forKey: "savedTitle")
saveData.setValue(scannedText, forKey: "savedText")
saveData.setValue(imageRep, forKey: "savedImage")
do{
try context.save()
}catch{
print("Failed")
}
How would I go about adding a lower level of data, one to hold a group of strings and one to hold a group of images?
I have been trying to structure it for hours and simply can not figure it out.
I hope the images can add context to what I am asking.
How would I go about adding a lower level of data, one to hold a group of strings and one to hold a group of images?
Don't have a group of strings and a separate group of images (how would you know which string belongs to which image?). A ScannedItem object already has both the string and the image, so you should group Scanned Item objects together to make an album.
In CoreData terms, you would create a new entity, Album. That entity might have its own attributes, such as a albumName or a albumDescription, plus a relationship to represent the ScannedItems in the album. Since an Album is a collection of many ScannedItems, the relationship would be "to-many".
In CoreData, if you define a relationship from one entity to another, you should always create the inverse relationship as well. The question to ask yourself is whether each ScannedItem can be in more than one Album? If so, the inverse relationship is also "to-many"; if not, the inverse is "to-one".
By default, CoreData represents the collection of objects in a to-many relationship as a Set. This has two consequences:
first, there is no implicit ordering of the objects in a set. If the order is important, you could either make the relationship "ordered" (in which case CoreData uses an ordered set), or you could specify a sort order (eg. in ascending alphabetical order of title) when you access the objects in the relationship. If the user can pick and choose the order in an Album, you might need to explicitly model the sort order by adding a sortOrder attribute. That's easy enough if the relationship from ScannedItem to Album is to-one, but if the relationship is to-many, the ScannedItem might be the first image in one Album but the last image in a different Album.
second, a set can only hold a given object once. So an Album cannot contain the same ScannedItem more than once.
The solution for each is the same: create a third entity, which you might call an AlbumScanReference, which has a sortOrder attribute, a to-one relationship to Album and a to-one relationship to ScannedItem. The inverse relationships would both be to-many: an Album could have many AlbumScanReferences and a ScannedItem could also have many AlbumScanReferences.
If myScan1 was the first item in album1 and seventh item in album2, you would create two AlbumScanReferences:
let reference1 = ....
reference1.scannedItem = myScan1
reference1.album = album1
reference1.sortOrder = 1
let reference2 = ....
reference2.scannedItem = myScan1
reference2.album = album2
reference2.sortOrder = 7
Likewise if myScan2 was the second item and the eighth item in album1, you would have two AlbumScanReferences:
let reference3 = ....
reference3.scannedItem = myScan2
reference3.album = album1
reference3.sortOrder = 2
let reference4 = ....
reference4.scannedItem = myScan2
reference4.album = album1
reference4.sortOrder = 8
I want to be able to save an array to core data. I am aware that this can't be done.
In this case, I have an entity named 'List' and an attribute called 'items'. You can see why an array would be helpful, I am able to save it with the Transformable type as an NSObject, but I can't access the individual elements once it has been pulled out of core data as an NSObject.
Can anybody tell me either how to go about saving an array in Core Data or how to use my NSObject to fix my problem
You do not want to save an array to Core Data, you want to create an entity called Item (or even ListItem) that has a one to many relationship with your entity called List. You would call the one -> many (List -> ListItem) property items and the many -> one (ListItem -> List) would be called list.
From there you can access both sides of the relationship via those properties.
That is how you should be handling this situation in Core Data.
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.
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.