Can't load images from "Documents" folder in iPhone/iPhone Simulator - ios

I have a part which is supposed to save an image into my phone's "Documents" folder and then access it. It saves fine, but the load methods don't really work. Here's my .m code:
- (UIImage*)loadImage
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:
#"photo.png" ];
UIImage *image = [UIImage imageWithContentsOfFile:path];
return image;
studentImage = [[UIImageView alloc] initWithImage: image]; //UIImageView property
}
- (UIImage*)loadBarcode
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:
#"barcode.png" ];
NSLog(#"%#", path);
UIImage *image = [UIImage imageWithContentsOfFile:path];
return image;
barcode = [[UIImageView alloc] initWithImage: image]; // UIImageView property
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self loadBarcode];
[self loadImage];
}
The files are definitely there to access, the file paths are correct. But the UIImageViews I'm trying to assign them to come up blank. I'm running out of options. Do you guys have any suggestions as to what it might be?

In loadImage method, the problem is here:
return image;
studentImage = [[UIImageView alloc] initWithImage: image];
You first use return statement which transfers the control and never assign it to the UIImageView control.
It should be something like:
studentImage = [[UIImageView alloc] initWithImage: image];
return image;
One more point, if studentImage is connected through IB, DON'T re-allocate it. Instead use:
studentImage.image = image;
Hope it helps!

Problem is fixed now, was an issue with my property names, but thank you for helping me clean up my code!

Related

How to I convert a UIImage to a PDF file in xcode?

In xcode, how would I convert a UIImage into a PDF File? Once I figure this out, I will send it through an email. But everything I've found while researching, it results as a blank file or gives an error saying it's damaged. How should I convert it?
-(void)createPdf:(NSImage*)image
{
PDFDocument *pdf = [[PDFDocument alloc] init];
NSImage *image = [[NSImage alloc] initWithContentsOfFile:fileName];
PDFPage *page = [[PDFPage alloc] initWithImage:image];
[pdf insertPage:page atIndex: [pdf pageCount]];
[pdf writeToFile:path];
}
USE the above method as follow :
NSImage *image = [[NSImage alloc] initWithContentsOfFile:PATH_OF_YOUR_PNG_FILE];
[self createPdf:image];
PDFDocument Class conforms to NSObject. You can use this PDFDocument class in the PDFKit Framework.
1. Download Source File From Step 4
2. Import into your Project
3. Put This code into your action
NSData *pdfData = [[NSData alloc] init];
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
pdfData = [PDFImageConverter convertImageToPDF:chosenImage];
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent: #"Documents/image.pdf"];
[pdfData writeToFile:path atomically:NO];
4. Enjoy PDFImageConverter
First you need to create a PDF graphics context that is GraphicsBegin and GraphicsEndPDFContext. Your image from current view will capture and it will set on your PDF page.
Steps:
First call this method on any of your button tap event:
NSString *fileName = [NSString stringWithFormat:#“pdf file name here”];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pdfFileName = [documentsDirectory stringByAppendingPathComponent:fileName];
// This method will generate pdf file of your image. You can send that pdf file after this method.
[self generatePdfWithFilePath: pdfFileName];
Then set these methods in your view controller:
- (void) generatePdfWithFilePath: (NSString *)thefilePath
{
UIGraphicsBeginPDFContextToFile(thefilePath, CGRectZero, nil);
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, 500, 810), nil);
[self drawImage:#“page number of pdf file”];
UIGraphicsEndPDFContext();
}
- (void) drawImage:(NSInteger)pageNumber
{
UIImage * demoImage1;
demoImage1 = [self captureView:#“Your image view”];
[demoImage1 drawInRect:CGRectMake(0, 0, 500, 810)];
}
- (UIImage *)captureView:(UIView *)view {
CGRect screenRect = view.frame;
UIGraphicsBeginImageContext(screenRect.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[[UIColor blackColor] set];
CGContextFillRect(ctx, screenRect);
[view.layer renderInContext:ctx];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

Due to heavy images stored in document directory app is receiving memory warning. And app get crashed

I am working on a app which is highly dependent on saving images in document directory and retrieving it and displaying it on screen.
As soon as I display 5 -6 images in collection view the ap gets slowed up and suddenly receives memory warning and stopes functioning and app crashes.
I am using following code to display data
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
DocumentCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"DocumentCollectionViewCell"
forIndexPath:indexPath];
if(cell!=nil){
cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"DocumentCollectionViewCell" forIndexPath:indexPath];
}
Documents *documents = [arrTableData objectAtIndex:indexPath.row];
cell.imgView.contentMode = UIViewContentModeScaleAspectFit;
cell.imgContentView.layer.cornerRadius = 4.0f;
cell.imgContentView.layer.masksToBounds = YES;
cell.imgContentView.layer.borderColor = [UIColor lightGrayColor].CGColor;
cell.imgContentView.layer.borderWidth = .4f;
[cell.btnLockOrUnlock addTarget:self action:#selector(lockAction:) forControlEvents:UIControlEventTouchUpInside];
cell.btnLockOrUnlock.tag = indexPath.row;
// set count
cell.lblCount.text =[NSString stringWithFormat:#"%# Page",documents.imageCount];
cell.imgView.layer.cornerRadius = 6.0f;
cell.imgView.layer.masksToBounds = YES;
newDocDate = documents.issueDate;
// set image
NSString * passcode = documents.passcode;
if(passcode.length>3){
cell.bluredView.hidden = NO;
[cell.btnLockOrUnlock setImage:[UIImage imageNamed:#"lockWhite"] forState:UIControlStateNormal];
}
else{
[cell.btnLockOrUnlock setImage:[UIImage imageNamed:#"unlockWhite"] forState:UIControlStateNormal];
cell.bluredView.hidden = YES;
}
[cell.btnSelect addTarget:self action:#selector(cellSelectAction:) forControlEvents:UIControlEventTouchUpInside];
cell.btnSelect.tag = indexPath.row;
NSString *title = documents.title;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Fetch path for document directory
NSString * docDirectoryPath = (NSMutableString *)[documentsDirectory stringByAppendingPathComponent:title];
//-----------------path of document ------------------
NSString *filePath = [docDirectoryPath stringByAppendingPathComponent:[NSString stringWithFormat:#"image%d.png",0]];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
int i =0;
while (!fileExists) {
filePath = [docDirectoryPath stringByAppendingPathComponent:[NSString stringWithFormat:#"image%d.png",i]];
fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
i++;
}
CGImageSourceRef src = CGImageSourceCreateWithURL((__bridge CFURLRef) [NSURL fileURLWithPath:filePath], NULL);
// Create thumbnail options
CFDictionaryRef options = (__bridge CFDictionaryRef) #{
(id) kCGImageSourceCreateThumbnailWithTransform : #YES,
(id) kCGImageSourceCreateThumbnailFromImageAlways : #YES,
(id) kCGImageSourceThumbnailMaxPixelSize : #(cell.imgView.frame.size.height)
};
// Generate the thumbnail
CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options);
UIImage* uiImage = [[UIImage alloc] initWithCGImage:thumbnail]; //<--CRASH
cell.DocName.text = documents.docName;
//-----------------display image on cell------------------
cell.imgView.image = uiImage;
uiImage = nil;
uiImage = NULL;
documents = nil;
documents = nil;
title = nil;
thumbnail = nil;
src = nil;
options = nil;
filePath = nil;
paths = nil;
documentsDirectory = nil;
docDirectoryPath = nil;
return cell;
}
I am setting all the objects to nil.
I am using following code to save images
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Fetch path for document directory
folderName = (NSMutableString *)[documentsDirectory stringByAppendingPathComponent:folderName];
NSData *pngData = UIImagePNGRepresentation(arrImages[i]);
NSString *filePath = [folderName stringByAppendingPathComponent:[NSString stringWithFormat:#"image%d.png",i]]; //Add the file name
[pngData writeToFile:filePath atomically:YES]; //Write the file
I save the original image from camera without any compression or resizing in document directory.
I am unable to understand the problem please help.
Thanks in advance.
It seems to be due to memory leaks, check your app using instruments and lacks tool.
CGImageSourceRef src = CGImageSourceCreateWithURL((__bridge CFURLRef) [NSURL fileURLWithPath:filePath], NULL);
// Create thumbnail options
CFDictionaryRef options = (__bridge CFDictionaryRef) #{
(id) kCGImageSourceCreateThumbnailWithTransform : #YES,
(id) kCGImageSourceCreateThumbnailFromImageAlways : #YES,
(id) kCGImageSourceThumbnailMaxPixelSize : #(cell.imgView.frame.size.height)
};
// Generate the thumbnail
CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options);
UIImage* uiImage = [[UIImage alloc] initWithCGImage:thumbnail]; //<--CRASH
CFFoundation objects follow similar memory management rules (If you create or copy you need to release it) of Obj-C before ARC (ARC doesn't manage core foundation objects).
In the code you have shown I see that you aren't releasing the CGImageRef and the CGImageSourceRef, this create two leaks and probably the crash.
Collection view cells are recycled thus the number of image opened in memory are basically the number of cells you are seeing on screen they should be the cause of your crash.

Image not loading correctly in app

My app lets the user select the photo from camera roll or take the photo, the app saves the photo locally and then goes to the next view controller and loads the image that was just saved and displayed on an image view.
This is the code that I used to get the image the user wanted and sent it to my send picture method.
UIImage *image = info[UIImagePickerControllerEditedImage];
[self saveImage:image];
[picker dismissViewControllerAnimated:NO completion:NULL];
[self performSegueWithIdentifier:#"switch" sender:nil];
Which is this:
-(void)saveImage: (UIImage*)image{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:#"test.png"];
NSData* data = UIImagePNGRepresentation(image);
[data writeToFile:path atomically:YES];
printf("image saved");
}
That code ran because it printed the image was saved. The app goes to the next view and this is how I set up my viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
//[imageViewPreview setImage:self.secondImage];
//imageViewPreview.image = self.secondImage;
}
I commented out both ways that I've tried but neither of those works. This is how I was trying to get my secondImage to load:
-(UIImage* )secondImage{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:#"test.png"];
UIImage* image = [UIImage imageWithContentsOfFile:path];
printf("image loaded");
return image;
}
what is wrong here?
You should do this much simpler. In your second view controller add a public UIImage property. Then import the second controller into the first one. Then in prepareForSegue set it the image like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"switch"]) {
ClassOfDEstinationController *destinationController = segue.destinationViewController;
destinationController.image = image;
}
}

Writing/loading to/from file

Im trying to learn how to save/load images, and i just don't get why this wont work. Im writing a screenshot to the filesystem like this:
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)])
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, [UIScreen mainScreen].scale);
else
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * data = UIImagePNGRepresentation(image);
NSArray *directories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [directories objectAtIndex:0];
NSString *key = [documentsDirectory stringByAppendingPathComponent:#"screenshots.archive"];
[data writeToFile:key atomically:YES];
And in the "init" medthod in my UITableView subclass, i do this:
pics = [[NSMutableDictionary alloc]initWithContentsOfFile:[self dataFilePath]];
dataFilePath method:
- (NSString *)dataFilePath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:#"screenshots.archive"];
}
To test if this works i have this delegate method:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return pics.count;
}
I test it by taking a screenshot, and then initializing my UITableview subclass, but it show no rows. What am i doing wrong?
There are a few key issues with the code that are causing it to not work. You're storing the image data directly to the file and trying to read it back as a dictionary. You'll want to wrap the image in an array first, and write the array to the file. Then you'll want to read the file into an array for the table to display. To sum up the changes:
Change
[data writeToFile:key atomically:YES];
to
NSMutableArray *storageArray = [NSMutableArray arrayWithContentsOfFile:key];
if(!storageArray)
storageArray = [NSMutableArray arrayWithObject:data];
else
[storageArray addObject:data];
[storageArray writeToFile:key atomically:YES];
and change
pics = [[NSMutableDictionary alloc]initWithContentsOfFile:[self dataFilePath]];
to
pics = [[NSArray alloc] initWithContentsOfFile:[self dataFilePath]];

Saving an Image in App Directory instead of going to photo album. Objective C iOS

Hello I have an app that takes pictures but doesn't save. I know how to save the image to the Photo Album but I need the image to go to the app's directory and will not show up in the Photos gallery. I already have searched and I failed to look for a working one. I also need that image to be in my UIImageView when I open my app. Here are my codes:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate> {
UIImagePickerController *picker;
UIImagePickerController *picker2;
UIImage *image;
IBOutlet UIImageView *imageView;
}
-(IBAction)TakePhoto;
-(IBAction)ChooseExisting;
- (IBAction)btnSave:(id)sender;
- (IBAction)btnLoad:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
-(IBAction)TakePhoto{
picker = [[UIImagePickerController alloc]init];
picker.delegate=self;
[picker setSourceType:UIImagePickerControllerSourceTypeCamera];
[self presentViewController:picker animated:YES completion:NULL];
// [picker release];
}
- (UIImage*)loadImage
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithFormat: #"MyImage.png"] ];
image = [UIImage imageWithContentsOfFile:path];
return image;
}
-(IBAction)ChooseExisting{
picker2 = [[UIImagePickerController alloc]init];
picker2.delegate=self;
[picker2 setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
[self presentViewController:picker2 animated:YES completion:NULL];
// [picker release];
}
- (IBAction)btnSave:(id)sender {
if (image != nil)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithFormat: #"MyImage.png"]];
NSData* data = UIImagePNGRepresentation(image);
[data writeToFile:path atomically:YES];
NSLog(#"saved");
}
}
- (IBAction)btnLoad:(id)sender {
[self loadImage];
}
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
image = [info objectForKey:UIImagePickerControllerOriginalImage];
[imageView setImage:image];
[self dismissViewControllerAnimated:YES completion:NULL];
}
- (void)viewDidLoad
{
[self loadImage];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
The Save and loadImage methods don't work :(. No idea why but I don't have any errors.
Your image saving/loading code seems correct.
Check if your IBActions are properly connected in IB.
And change:
- (IBAction)btnLoad:(id)sender
{
[self loadImage];
}
to:
- (IBAction)btnLoad:(id)sender
{
[self loadImage];
[imageView setImage:image];
}
Your original code seems to load the image but it doesn't show it anywhere.
EDIT:
You can always check if the image is saved to documents directory.
With the device connected open the organizer window in XCode.
Select your device, then select applications. Choose the application
you're interested in and you should see the file-tree related to that
app. Is your image file listed in the Documents folder?
Check in documents directory for image. Your calling [self loadImage]; but loadImage return UIImage which your not using anywhere. You can attach data to picker like the following.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:#"MyImage.png"];
NSData *myData = [[[NSData alloc] initWithContentsOfFile:appFile] autorelease];
[picker2 addAttachmentData:myData mimeType:#"image/png" fileName:#"MyImage"];

Resources