Writing/loading to/from file - ios

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]];

Related

How to generate multi page pdf file with Array of multiple images in iOS programmatically?

Hi i need to generate a pdf file of multiple pages with array of multiple images can any one help me with sample code please?
I slightly changed the previous solution. This method accept the name for the new file and an array of images and returns the absolute path to the pdf.
- (NSString *)createPdfWithName: (NSString *)name array:(NSArray*)images {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docspath = [paths objectAtIndex:0];
NSString *pdfFileName = [docspath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.pdf",name]];
UIGraphicsBeginPDFContextToFile(pdfFileName, CGRectZero, nil);
for (int index = 0; index <[images count] ; index++) {
UIImage *pngImage=[images objectAtIndex:index];;
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, (pngImage.size.width), (pngImage.size.height)), nil);
[pngImage drawInRect:CGRectMake(0, 0, (pngImage.size.width), (pngImage.size.height))];
}
UIGraphicsEndPDFContext();
return pdfFileName;
}
You can use these methods to generate a PDF file containing images:
- (void) generatePdfWithFilePath: (NSString *)thefilePath
{
NSArray *pathsImage = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docspath = [pathsImage objectAtIndex:0];
NSString *dataPath = [docspath stringByAppendingPathComponent:folder];
NSString *imagepath=[dataPath stringByAppendingPathComponent:imageName];
UIGraphicsBeginPDFContextToFile(thefilePath, CGRectZero, nil);
NSInteger currentPage = 0;
BOOL done = NO;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *folder=[NSString stringWithFormat:#"ImageFolder"];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:folder];
UIImage *imgBrush = [UIImage imageWithContentsOfFile:imagepath];
for (int i=0; i<directoryContent.count; i++) {
[self drawImage:imgBrush];
}
}
- (void) drawImage :(UIImage*) imgBrush
{
if (imgBrush.size.width > pdfpageSize.width || imgBrush.size.height > pdfpageSize.height) {
[imgBrush drawInRect:CGRectMake((pdfpageSize.width/2)-(imgBrush.size.width/4), (pdfpageSize.height/2)-(imgBrush.size.height/4), imgBrush.size.width/2, imgBrush.size.height/2)];
} else {
[imgBrush drawInRect:CGRectMake((pdfpageSize.width/2)-(imgBrush.size.width/2), (pdfpageSize.height/2)-(imgBrush.size.height/2), imgBrush.size.width, imgBrush.size.height)];
}
}
Hey here is another method that you can use to render images in a PDF through code:
-(void)drawImagesToPdf:(UIImageView *)button
{
CGSize pageSize = CGSizeMake(button.frame.size.width*5, button.frame.size.height*5+30);
NSLog(#"page size %#",NSStringFromCGSize(pageSize));
NSString *fileName = #"Demo.pdf";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pdfFileName = [documentsDirectory stringByAppendingPathComponent:fileName];
UIGraphicsBeginPDFContextToFile(pdfFileName, CGRectMake(0, 0, button.frame.size.width, button.frame.size.height*3), nil);
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0.0, pageSize.width, pageSize.height), nil);
NSArray *arrImages = [NSArray arrayWithObjects:#"3.png", #"4.png", #"5.png", #"6.png", nil];
float y = 220.0;
for (int i=0; i<arrImages.count; i++) {
UIImage * myPNG = [UIImage imageNamed:[arrImages objectAtIndex:i]];
[myPNG drawInRect:CGRectMake(50.0, y, myPNG.size.width, myPNG.size.height)];
y += myPNG.size.height + 20;
}
UIGraphicsEndPDFContext();
}
Try my updated code...
Hope this is helpful to you...
All the best..!!!
Make an array of actual images not names.
NSMutableArray *arr=[[NSMutableArray alloc]initWithObjects:[UIImage imageNamed:#"image1.png"],[UIImage imageNamed:#"image2.png"],nil];
use this and make sure your application bundle contain images with names image1.png and image2.png

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

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!

Using iCarousel with images in folder

I have a folder (Documents/Images) which I use to store images downloaded from online, when the view with iCarsousel is launched infomation on which images to use is also sent so only certain images from the folder will be used.
However for some reason the below code does not seem to work and a blank view is shown and no error message given.
- (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel
{
[carousel setType:iCarouselTypeCylinder];
[self getImages];
return [images count];
}
- (void)getImages{
images=[[NSMutableArray alloc]init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:databaseName];
db = [FMDatabase databaseWithPath:writableDBPath];
if (![db open]) {
return;
}
NSLog(#"getting images");
NSLog(_galleryid);
FMResultSet *result = [db executeQuery:#"SELECT * FROM mediaImages WHERE galleryID = ?;", _galleryid];
while ([result next]){
NSString *filename = [result stringForColumnIndex:1];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSFileManager *fileManager = [NSFileManager defaultManager];
//configure carousel
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:#"Images"];
NSString *filepath = [fPath stringByAppendingString:#"/"];
filepath = [filepath stringByAppendingString:filename];
NSLog(filepath);
[images addObject:filepath];
}
}
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
view = [[UIView alloc] init];
view.contentMode = UIViewContentModeScaleAspectFit;
CGRect rec = view.frame;
if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone)
{
rec.size.width = 250;
rec.size.height = 250;
}
view.frame = rec;
UIImageView *iv;
if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone)
{
iv=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 200, 200)];
}
NSString *temp=[images objectAtIndex:index];
iv.image=[UIImage imageNamed:temp];
iv.contentMode = UIViewContentModeScaleAspectFit;
[view addSubview:iv];
return view;
}
- (void)carousel:(iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index
{
NSLog(#"Image is selected.");
}
- (CGFloat)carousel:(iCarousel *)carousel valueForOption:(iCarouselOption)option withDefault:(CGFloat)value
{
switch (option)
{
case iCarouselOptionWrap:
{
return YES;
}
default:
{
return value;
}
}
}
Is there anything visably wrong with the code, or perhaps a good way to debug what the issue is?
My guess is that the problem is here:
iv.image=[UIImage imageNamed:temp];
temp is a path to a file, not the name of an image, so this won't work. Perhaps you want to use + imageWithContentsOfFile: instead?
If that's not the only problem, I highly recommend trying to isolate it further yourself with logging or debugging; for example if you had logged the value of temp and the image you get back from imageNamed:, you probably would have seen this problem as well.

Save and Get image from plist

I am developing one app in that getting images from array and display vertically in ScrollView.
when user double tapped on particular image i want that exact image store into plist according to tag value of that image, and retrieve that image later on when require.
i tried this one
// Store Data into plist.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *path = [NSString stringWithFormat:#"%#/myPlist.plist",
[paths objectAtIndex:0]];
// Place an image in a dictionary that will be stored as a plist
NSMutableDictionary * dictionary=[[NSMutableDictionary alloc]init];
[dictionary setObject:ImgView.tag forKey:#"image"];
NSLog(#"%#",dictionary);
// Write the dictionary to the filesystem as a plist
[NSKeyedArchiver archiveRootObject:dictionary toFile:path];
// For getting data from NSmutable array store it to the scrollview.
int m=0;
AppDelegate * delegate=(AppDelegate *)[[UIApplication sharedApplication]delegate];
delegate.front=TRUE;
delegate.back=FALSE;
UIScrollView *scrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
[scrollView setPagingEnabled:YES];
[scrollView setShowsHorizontalScrollIndicator:NO];
FrontsCards=[[NSMutableArray alloc]initWithObjects:#"cloub1.png",#"cloub2.png",#"cloub3.png",#"cloub4.png",#"cloub5.png",#"cloub6.png",#"cloub7.png",#"cloub8.png",#"cloub9.png",#"cloub10.png",#"cloub11.png",#"cloub12.png",#"diamond1.png",#"diamond2.png",#"diamond3.png",#"diamond4.png",#"diamond5.png", nil];
for(m=0; m<[FrontsCards count];m++)
{
ImgView.alpha=1;
ImgView.tag=m;
int randIdx=arc4random()%[FrontsCards count];
NSString *imageName=[FrontsCards objectAtIndex:randIdx];
NSString *fullImageName=[NSString stringWithFormat:#"%#",imageName];
int padding=0;
CGRect imageViewFrame=CGRectMake(scrollView.frame.size.width*m+padding, scrollView.frame.origin.y, scrollView.frame.size.width-2*padding, scrollView.frame.size.height);
ImgView=[[UIImageView alloc]initWithFrame:imageViewFrame];
[ImgView setImage:[UIImage imageNamed:fullImageName]];
NSLog(#"%d",m);
// Place an image in a dictionary that will be stored as a plist
//[dictionary setObject:image forKey:#"image"];
// Write the dictionary to the filesystem as a plist
//[NSKeyedArchiver archiveRootObject:dictionary toFile:path];
[scrollView addSubview:ImgView];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doubleTapImgView:)];
doubleTap.numberOfTapsRequired = 2;
doubleTap.delegate = self;
[self.ImgView addGestureRecognizer:doubleTap];
self.ImgView.userInteractionEnabled=YES;
}
CGSize scrollViewSize=CGSizeMake(scrollView.frame.size.width*[FrontsCards count], scrollView.frame.size.height);
[scrollView setContentSize:scrollViewSize];
[self.view addSubview:scrollView];
help me out this thanks in advance.
Define this MACRO Definition at the top of your .m file
#define LIB_DIR_PATH NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)[0]
Use this function to Save Image to Plist with Image and Name
- (void)saveImage:(UIImage *)image WithName:(NSString *)imageName
{
// If File Exist then read it otherwise creat new
NSMutableDictionary *imageInfoDict;
if([[NSFileManager defaultManager] fileExistsAtPath:[LIB_DIR_PATH stringByAppendingPathComponent:#"imageInfo.plist"]])
{
NSData *fileData = [NSData dataWithContentsOfFile:[LIB_DIR_PATH stringByAppendingPathComponent:#"imageInfo.plist"]];
imageInfoDict = [NSMutableDictionary dictionaryWithDictionary:[NSKeyedUnarchiver unarchiveObjectWithData:fileData]];
}
else
imageInfoDict = [NSMutableDictionary dictionaryWithCapacity:0];
// Add Single Image to Dictionary
[imageInfoDict setValue:image forKey:imageName];
// Convert Main info Dictionary to `NSData` to Save on Disc
[NSKeyedArchiver archiveRootObject:imageInfoDict toFile:[LIB_DIR_PATH stringByAppendingPathComponent:#"imageInfo.plist"]];
// To Read Stored Image Use Following Code
[self readImageFromPlistByKey:imageName];
}
This function returns image for respective name from Plist
-(UIImage *)readImageFromPlistByKey:(NSString *)keyName
{
// If File Exist then read it otherwise creat new
NSMutableDictionary *imageInfoDict;
if([[NSFileManager defaultManager] fileExistsAtPath:[LIB_DIR_PATH stringByAppendingPathComponent:#"imageInfo.plist"]])
{
NSData *fileData = [NSData dataWithContentsOfFile:[LIB_DIR_PATH stringByAppendingPathComponent:#"imageInfo.plist"]];
if([fileData length] > 0)
{
// Read Plist
imageInfoDict = [NSMutableDictionary dictionaryWithDictionary:[NSKeyedUnarchiver unarchiveObjectWithData:fileData]];
// Here is your Image
return imageInfoDict[keyName];
}
}
else
{
// Return Default Image if not Found
return [UIImage imageNamed:#"Default.png"];
}
}
If you are going to just store indexes, you need to have a master imageArray. I added insert/delete when user double taps the imageView twice.
- (void)doubleTapImgView:(UITapGestureRecognizer *)recognizer
{
UIImageView *imageView = (UIImageView *)recognizer.view;
[self insertorDeleteImageIndex:imageView.tag-1];
}
- (NSString *)plistFilePath{
NSString *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
return [documents stringByAppendingPathComponent:#"ImageIndexes.plist"];
}
- (void)insertorDeleteImageIndex:(NSInteger)index{
NSString *filePath = [self plistFilePath];
NSMutableArray *savedIndexes = [NSMutableArray arrayWithContentsOfFile:filePath];
if (!savedIndexes) {
savedIndexes = [NSMutableArray array];
}
if (![savedIndexes containsObject:#(index)]) {
[savedIndexes addObject:#(index)];
}else{
[savedIndexes removeObject:#(index)];
}
[savedIndexes writeToFile:filePath atomically:YES];
}
- (NSArray *)savedImageIndexes{
NSString *filePath = [self plistFilePath];
return [NSArray arrayWithContentsOfFile:filePath];
}
Source code
The code you post above can't be the real code as it wouldn't compile. That said, it shows a few errors:
You can't put basic numbers (NSInteger) into a dictionary, it needs to be boxed in an NSNumber.
You're setting the tag of the image before you create the instance of the image view (so either it will do nothing or set the wrong tag).
For saving the image, if you do want to save the image instead of the tag, you need to save it as data. You can store an image inside a dictionary no problem, but if you then want to store your dictionary as a plist you need to convert the image to NSData. You can get the image data using:
UIImageJPEGRepresentation(imageToSave, 0.8)

Writing new keys to a .plist file based on textField

What I want to do is to populate a pickerView from an array based on a .plist, which can be added to from a textField. I've got it to work, but it only adds one key and replaces it when a new one is added. For instance if I add "hello", and then try to add another one, it replaces hello with something else.
- (IBAction)setContext:(id)sender {
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [[NSBundle mainBundle] pathForResource:#"fullArray" ofType:#"plist"];
NSString *textFieldText = textField.text;
NSMutableDictionary *rootDict = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
[rootDict setValue:textField.text forKey:textField.text];
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:#"fullArray.plist"];
[rootDict writeToFile:writablePath atomically: YES];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //1
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:#"fullArray.plist"]; //3
NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
NSArray *array = [dictionary allKeys];
arrayContext = [[NSMutableArray alloc] initWithArray:array];
[pickerView selectRow:0 inComponent:0 animated:YES];
[textField endEditing:YES];
[pickerView reloadAllComponents];
}
How can I fix this?
Ok, you are creating a new NSMutableDictionary every time you pick something in the picker, the correct approach is:
Create a NSMutableDictionary as a property.
Every time you pick, create a new string for the key, maybe using [NSString stringWithFormat:].
use [mutableDictionary setObject:forKey] for set a new object in the mutant dictionary, with the new created key.

Resources