save images to core data using magical record - image

I'm using magical record with Core Data.
In my app I have just one entity with some string attributes. Now, I would like to add an image to this entity, but I don't have any idea of how to do that using magical record. I searched but haven't found anything on the web. In my app all the data is inserted by the user, so also the image, by the camera or the photo library.
How do I store images using Magical Record and Core Data?

Just store the image in the documents folder of the app and save a string with the file url in the core data entity.

What you're trying above can be done easily. Best advice i can give you is make a new sample project just to save and retrieve image from the CoreData database. That way you know exactly how the process works. If you try to embed this functionality in your current project you might loose track of what happening where.
This is very quick example, i'll expect you to import the Delegates in your .h files yourself etc.
First initiate the UIImagePicker via button
-(IBAction)pickImage:(id)sender
{
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
[self presentModalViewController:imagePicker animated:YES];
}
Once the image is selected, you can display it on the button using one of the delegate methods
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)selectedImage editingInfo:(NSDictionary *)editingInfo
self.imageButton.imageView.image = selectedImage;
To save it to CoreData assign your UIImage type to a Transformable type in your attribute in your database and then save the managedObjectContext
Links to help you:
UIImagePicker Class Reference
Magical Record Docs
CoreData Recipes Sample Project
Hope this help, good luck!

I found my answer:
to save:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString*nomeImmagine = [[NSString alloc] initWithFormat:#"%#", self.fieldName.text];
NSString *pngFilePath = [NSString stringWithFormat:#"%#/%#.png",documentsDirectory, nomeImmagine];
UIImage *image = self.showSelectedImage.image; // imageView is my image from camera
NSData *data1 = [NSData dataWithData:UIImagePNGRepresentation(image)];
[data1 writeToFile:pngFilePath atomically:NO];
to load:
-(void) loadImageFromPathInsideView
{
// [self loadImageFromPathInsideView];
Ricetta* contact =[[DataManager sharedClass]dammiTuttaLaRicetta:self.indice];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString*nomeImmagine = [[NSString alloc] initWithFormat:#"%#", contact.nome2];
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [NSString stringWithFormat:#"%#/%#.png",documentsDirectory, nomeImmagine];;
UIImage* image = [UIImage imageWithContentsOfFile:path];
self.image.image = image;
}

a word of advice. storing images as transformable (aka NSImage) type in core data is easy, but leads to overall slow app performance for even a low number (over 20) that range from 50k to 200kb with an average of 100k. even having those files linked via a relationship is slow, considering that one controller is often bound to another.
the above method of storing a local path name as a NSString pointing to Documents folder is heaps better for the overall experience.
that being said, creating a thumbnail image (of around 150x150) can be advantageous to create once and store that as a transient transformable NSImage, rather than loading the biggy and doing an on-the-fly resize a number of times. that performance can be observed easily scrolling up and down in a Table holding 50+ thumbnail images.

Related

Xcode Parse cachePolicy seems to break my thread

so i'm fairly new to Xcode and C# so this may be a silly question, but none-the-less it has had me tearing my hair out for 3 days now.
Ok, so I am using Parse to fetch and save data, images, etc. I want to display a UITableView with the PFFile images. This bit I have managed.
The issue I have is the the scrolling performance is bad because i'm not caching the PFFile images that come in. I have no idea how to do this and any searches i make don't take into account using parse.
below is my code that puts the initial data into an array:
-(void) retrieveFromParse {
PFQuery *retrieveContent = [PFQuery queryWithClassName:#"NewsFeed"];
[retrieveContent orderByDescending:#"createdAt"];
//[retrieveContent unpinInBackground];
//retrieveContent.cachePolicy = kPFCachePolicyCacheElseNetwork;
[retrieveContent findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if(!error){
mainArray = [[NSArray alloc] initWithArray:objects];
}
[tableView reloadData];
}];
}
This code then gets the images:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"MyCell";
TableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.profilePicture.layer.cornerRadius = cell.profilePicture.frame.size.height /1.99;
cell.profilePicture.layer.masksToBounds = YES;
cell.profilePicture.layer.borderWidth = 0;
PFObject *imageObject = [mainArray objectAtIndex:indexPath.row];
PFFile *imageFile = [imageObject objectForKey:#"image"];
[imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if(!error){
NSLog(#"%#",data);
cell.myImage.image = [UIImage imageWithData:data];
}
}];
return cell;
}
Now, you'll see i have commented out the cachePolicy because every time i use it, the thread breaks.
If someone could please alter my code or provide me with an example project using my code, to take into account caching either array and/or PFFile images, that would save me from going bald! :)
Many thanks in advance.
Did you tried retrieving the images in the viewdidload function instead of the cellForRowAtIndexPath?
I had the same problem before and I solved almost 90% of this problem by doing the following:
1- in the viewdidload, i wrote 2 queries: 1 for retrieving the data, and the other one to retrieve the images and store them in an array.
2- in the cellForRowAtIndexPath, i just added the images i got in the view did load to my cell.
this is what I did but unfortunately I'm still having a problem. The problem is that the images are not retrieved in the same order of retrieving the data "the image is not displayed next to the correct data :/".
I'm trying to solve this issue and if i did i will post the solution :)
Hope my Solution will help you. good luck ;)

How to load local images into UITableView without having impact on the scroll down performance?

Before somebody says something about this topic being duplicated several times, please note that I really don't need loading remote images from the web (SDWebImage github solution), I'm trying to load images dynamically saved on the documents folder, so they are local by the time I want to load them on my tableView having reference to them via a record on a sqlite table in which I saved the image name as it was generated by code.
So after parsing all my sqlite data, in my CellForRowAtIndexPath method at a certain point I have the following lines of code:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
NSString *imageName = [[favorites objectAtIndex:[indexPath row]] objectForKey:#"imagename"];
cell.image.image = [self loadImage: imageName]; // Is a custom cell so cell.image is a UIImageView, and I'm setting its image property
...
}
And my loadImage method looks like:
- (UIImage*)loadImage:(NSString*)imageName {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.png", imageName]];
return [UIImage imageWithContentsOfFile:fullPath];
}
Note also that this code actually works but scrolling down the table looks laggy. How can I improve the performance, I mean loading images in the background comes to my mind but the images are already there. Can someone give me a concrete solution on this please?
Just to let you know, I'm working with iOS 5 and ARC.
Any help would be very appreciated.
Firstly decrease the size of image you load.
Secondly try to use GCD to load image in tableView:cellForRowAtIndexPath:.

Adding custom metadata in PDFDocument

I'm sending a document between the desktop and a handheld device, and I want to add a metadata header to a PDF like the following.
<CUSTOM_HEADER>\n
{"fileInfoEncodedInJson\":
{"filename":"My Print Out",
"filesize\":"630",
"filedesc":"",}
}\n
</CUSTOM_HEADER>\n
… file contents …
I've been using the PDFKit and PDFDocument which supplies the documentAttributes and setDocumentAttributes methods, but because it is a custom header, it doesn't seem to persist when I set the attributes and save the file:
NSURL *path = [NSURL fileURLWithPath:#"/Users/username/Desktop/file.pdf"];
PDFDocument *document = [[PDFDocument alloc] initWithURL:path];
NSDictionary *docAttributes = [self.document documentAttributes];
NSMutableDictionary *newAttributes = [[NSMutableDictionary alloc] initWithDictionary:docAttributes];
[newAttributes setObject: #"Custom header contents" forKey:#"Custom header"];
docAttributes = [[NSDictionary alloc] initWithDictionary: newAttributes];
[document setDocumentAttributes: docAttributes];
//Here Custom Header is an entry in the dictionary
[self.document writeToFile:#"/Users/username/Desktop/UPDATEDfile.pdf"];
//Here the UPDATEDfile.pdf does not contain the custom header
I've been looking all over and I've found a couple of similar questions (like here on cocoadev for example) but no answers. Does anyone know of a way to store custom (i.e. not the 8 predefined constants provided under Document Attribute Keys) headers to PDF Files?
I didn't actually edit the pre-existing headers, I simply created a NSMutableData object, added the text data first followed by the PDF data, then saved this data to the path I wanted.
NSString *header = [NSString stringWithFormat:#"<CUSTOM_HEADER>\n {\"fileInfoEncodedInJson\": {\"filename\":\"My Print Out\", \"filesize\":\"630\",\"filedesc\":\"\",} }\n </CUSTOM_HEADER>\n"];
// Append header to PDF data
NSMutableData *data = [NSMutableData dataWithData:[header dataUsingEncoding:NSWindowsCP1252StringEncoding]];
[data appendData:[doc dataRepresentation]];
[data writeToFile:#"/Users/username/Desktop/UPDATEDfile.pdf" atomically:NO];
This results in a PDF file that opens in Adobe for me, and the header is invisible when viewing.

Cocoa core data project relationship insertion from popup button

I have a core-data with 2 entities: 'CarEntity' and 'PassengerEntity'.
Now, each entity has an attribute called 'name'. CarEntity has a to-many relationship with PassengerEntity called 'passengers' and PassengerEntity has the inverse relationship 'inCar'.
So, I did this interface to insert a new passenger.
I have one NSTextField for the person's name and one NSPopUpButton to chose the car.
The popup button has a "content values" binding to a NSControllerArray that allows me to get all the cars.
Then I have one button to save everything. The header code goes like this:
IBOutlet NSTextField *newPassengerNameField;
IBOutlet NSPopUpButton *newPersonCarField;
And the implementation goes like this:
- (IBAction)saveNewPassenger:(id)sender {
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSManagedObject *newPassengerObject = [
NSEntityDescription
insertNewObjectForEntityForName:#"PassengerEntity"
inManagedObjectContext:managedObjectContext
];
//Here we have all the fields to be inserted.
[newPassengerObject setValue:[newPassengerNameField stringValue] forKey:#"name"];
//Car ?????
}
Okay, this code works just fine.. for the name. But I can't figure out how to insert the car relationship.
My application forces the user to create a car before coming to this stage, so I have objects in the CarEntity.
The question is: How do I get the value of the popup button and send it to this insert code?
Thanks!
This pretty much works, but any help in the sense of cleaning the code is much appreciated!
[newPassengerObject setValue:[newPassengerNameField stringValue] forKey:#"name"];
//Continuing from old code.
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"name = %#", [[newPersonCarField selectedItem] title]];
NSEntityDescription *modelEntity = [NSEntityDescription entityForName:#"CarEntity" inManagedObjectContext:managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:modelEntity];
[fetchRequest setPredicate:predicate];
NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:nil];
[fetchRequest release];
[newPassengerObject setValue:[results objectAtIndex:0] forKey:#"inCar"];
//Code goes on from here.
// Code cleaning comments
1: Why do you use 'setValue:forKey'? Haven't you auto generated your Entity class files. If you had generated, you could have treated entities like custom objects. For eg. I am picking up your piece of code. It could be modified like below, if you had Entity class files
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
PassengerEntity *newPassengerObject = [
NSEntityDescription
insertNewObjectForEntityForName:#"PassengerEntity"
inManagedObjectContext:managedObjectContext
];
newPassengerObject.name = [newPassengerNameField stringValue];
2: Don't mix up core data code in your saveNewPassenger: method. It was not meant for Core Data operations. In that case, why do you write COre data code inside that method? It will only result in repetition of code. Better write an 'Interface Class' for communicating with Core Data. This will increase modularity and code reusability

how to get the path and url of the temp image?

I capture a image of webview that playing a flash. Because I want to show this image and use the IKSaveOptions to save the image .but I found the path of image is nil, Now I want to get the path of image , How to do ?
my code:
NSString *path = [[NSBundle mainBundle] pathForResource: ?? ofType:??];
NSURL *url = [NSURL fileURLWithPath: path];
then I use the url to show the image in the imageview,but Now I didn't get the path ,Thanks a lot!
thanks a lot. Now I think that the NSBundle is not my option. But I want to show the image of capturing it from a webview showing a flash. I can show it in a imagecell, but show in the imageview ,I use the code:
[imageView setImage:image imageProperties: mImageProperties];
and the mImageProperties come from ahead of the document of you take me the ImageKit documentation, the name is "Viewing an Image in an Image View" ,and in there the mImageProperties is the properties of image . code is :
mImageProperties = (NSDictionary*)CGImageSourceCopyPropertiesAtIndex(isr, 0, (CFDictionaryRef)mImageProperties);
still ues the url of the image, if I couldn't use the NsBundle , How I can do to get the properties of the image, by the way, I have already get the image of the capturing webview of showing a flash. code :
NSBitmapImageRep *imageRep = [webView bitmapImageRepForCachingDisplayInRect:[webView frame]];
[webView cacheDisplayInRect:[webView frame] toBitmapImageRep:imageRep];
NSImage *image = [[NSImage alloc] initWithSize:[webView frame].size];
[image addRepresentation:imageRep];
Okay, you are confusing a lot of things here. First off, IKSaveOptions does not save an imnage. It is a mechanism for presenting an interface to the user about the options the want for saving, but it does not actually save the file anywhere. To save the file you use the underlying CGImage mechanisms, as described in the ImnageKit documentation. I think if you read the example code there it will also be clear where the path to the saved file is.
Now, onto the second issue. You would never use pathForResource:ofType to get it. That gets resources that are in your application bundle. In other words, things that are a part of your application, that you include with it at build time. You should NEVER modify your bundle contents after build, aside from being complicated, it will invalidate codesigned applications. Instead you should probably use either CGImage or NSImage to read it in.
ok, I have the answer.
NSBitmapImageRep *imageRep = [webView bitmapImageRepForCachingDisplayInRect:tmpRect];
[webView cacheDisplayInRect:tmpRect toBitmapImageRep:imageRep];
NSImage *theimage = [[NSImage alloc] initWithSize:tmpRect.size];
[theimage addRepresentation:imageRep];
CGImageSourceRef isr = CGImageSourceCreateWithData((CFDataRef)[theimage TIFFRepresentation], NULL);
CGImageRef image = NULL;
if (isr)
{
image = CGImageSourceCreateImageAtIndex(isr, 0, NULL);
if (image)
{
mImageProperties = (NSDictionary*)CGImageSourceCopyPropertiesAtIndex(isr, 0, (CFDictionaryRef)mImageProperties);
}
CFRelease(isr);
}
if (image)
{
[imageView setImage:image imageProperties:mImageProperties];
CGImageRelease(image);
}

Resources