I have an array which has pictures stored in it which are taken from the camera, but when the app is closed or minimised they are all gone next time the app is started. What is the best way to fix this?
2 Answers
Instead of adding the image to an array why don't you save the images to your app documents folder like this:
//Save Image to Documents Directory
UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
NSString *imagePath = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"Documents/image.jpg"]];
[UIImageJPEGRepresentation(image, 1.0) writeToFile:imagePath atomically:YES];
Now you can always access the images anytime you are using the app.
Update #1:
Okay say you have more than one picture and you do not want to overwrite the images saved in your documents directory. I would do something like the following:
First create a method that returns the current date and time
- (NSString *)currentDateandTime
{
NSDate *today = [NSDate date];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"MMddyyyy_HHmmssSS"];
NSString *dateString = [dateFormat stringFromDate:today];
[dateFormat release];
return dateString;
}
As you can see the date is down to the millisecond, this prevents any chance of overwriting an image. To call the method see below:
//Set Photo Date
NSString *date = [self currentDateandTime];
Now onto saving the image:
//Save Image to Documents Directory
UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
NSString *imagePath = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"Documents/%@_image.jpg",date]];
[UIImageJPEGRepresentation(image, 1.0) writeToFile:imagePath atomically:YES];
By doing the above you have created a unique file name for the image. For example: 10212012_12182245_image.jpg
Now to retrieve the image. While you are saving the image you would also need to save the file name into a .PLIST file for example. You could create an array of the file names and save them to the disk as a PLIST file. Then you do things like sorting all the images by date or loading them by date.
Update #2:
Okay so you want to create and save to a PLIST. You can call this when the image picker loads.
- (void)createPLIST
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [path objectAtIndex:0];
NSString *plistPath = [documentsDirectory stringByAppendingString:@"/images.plist"];
//Check to see if the file exists, if not create the file.
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]){
//Creating empty Image Files Array for later use
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
[imageArray writeToFile:plistPath atomically:YES];
[imageArray release];
}
}
Now you have created the PLIST, you will need to load it when saving images and then write data to it. I would suggest creating a separate method that gets called every time you snap a picture. What is going to happen is this: 1.) Take Picture 2.) Save Picture with date and time attached to the file name 3.) Pass that date object to the method below. The method below is going to add values to the dictionary and save the dictionary back to the documents directory. Also on a side note since we are saving everything to the documents folder all of the information is backed up so the user will not lose their images when upgrading the app.
- (void)createNewGalleryObject:(NSString *)date
{
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [path objectAtIndex:0];
NSString *plistPath = [NSString stringWithFormat:@"%@/images.plist", documentsDirectory];
//Load PLIST into mutable array
NSMutableArray *imageArray = [NSMutableArray arrayWithContentsOfFile:plistPath];
//Create a dictionary for each image captured that saves basic information about the file for later use
NSMutableDictionary *newEntry = [[NSMutableDictionary alloc] init];
[imageArray addObject:newEntry];
//This is where we write to the dictionary, it is up to you what values to save.
//Based on what you told me I would save the information shown below.
//For example Later you can do things like sort by date.
[newEntry setValue:[NSDate date] forKey:@"Date"];
[newEntry setValue:[NSString stringWithFormat:@"Documents/%@_originalImage.jpg",date] forKey:@"Original Image"];
//Now save the array back to the PLIST, the array now contains a new dictionary object.
//Every time you take a picture a new dictionary object is created
[imageArray writeToFile:path atomically:YES];
[newEntry release];
}
Okay lets say you now have taken a bunch of pictures and stored the image information to your documents directory. You can do things like load all of the images in the array.
-(void)loadImages
{
//Load PLIST
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [path objectAtIndex:0];
NSString *plistPath = [NSString stringWithFormat:@"%@/images.plist", documentsDirectory];
//Load PLIST into mutable array
NSMutableArray *imageArray = [NSMutableArray arrayWithContentsOfFile:plistPath];
for (NSDictionary *dict in imageArray) {
//Do whatever you want here, to load an image for example
NSString *imageFilePath = [NSHomeDirectory() stringByAppendingPathComponent:[dict objectForKey:@"Original Image"]];
UIImage *image = [UIImage imageWithContentsOfFile:imageFilePath];
}
}
Rock on.

- 1,125
- 1
- 9
- 16
-
Because I am going to have a lot of images that are being accessed from the array, and put into a tableview and need these images to be in the right rows/order they are taken in. – Andrew Gierens Oct 21 '12 at 04:29
-
@stackmonster assuming they are stored there that is and if they are then I would suggest you read them when necessary rather than loading them all into an array – rogermushroom Oct 21 '12 at 04:30
-
@stackmonster That is not true. By default the images taken from the camera are not stored into the iOS photo library. That has to be done manually. In this case he needs the images for later use so storing them in the documents folder is the best way. – dana0550 Oct 21 '12 at 04:31
-
@AndrewGierens I understand what you are saying but either way you are going to have to write the images to the disk if you want to have them for later use. Then you can load all the images into an array for use in your table view. – dana0550 Oct 21 '12 at 04:33
-
No problem, if have any other questions let me know. – dana0550 Oct 21 '12 at 04:35
-
1@dana0550 The thing i dont understand about this is, if i am taking say 10 pictures at a time, what are the pictures going to be names in the Documents folder? Is it going to overwrite all the images because they are called "image.jpg"? Sorry if this is a stupid question – Andrew Gierens Oct 21 '12 at 05:10
-
@AndrewGierens Not a stupid question, actually very important. See my updated answer in a few minutes. – dana0550 Oct 21 '12 at 05:13
-
Why didn't i think of a date in the name! Perfect, thanks a lot! – Andrew Gierens Oct 21 '12 at 05:51
-
@dana0550 Wouldn't want to help me with the PLIST too would you? – Andrew Gierens Oct 21 '12 at 06:00
-
@AndrewGierens Sure! See Update #2. – dana0550 Oct 21 '12 at 13:58
-
@dana0550 That code seems perfect, accept for one thing, when is the "for (NSDictionary *dict in imageArray) " called? Because It doesn't seem to be being called at the moment. – Andrew Gierens Oct 21 '12 at 21:01
-
@AndrewGierens The line gets called when you need to load the imageArray. The array contains dictionary objects. Each dictionary contains information about that particular image. I would call this method when you are initially loading your table view with the images. If the array is empty then it will never get called. You can try logging the contents of the imageArray to make sure the dictionary items are being added to it. – dana0550 Oct 21 '12 at 21:23
-
I will try it a little later and let you know how it goes! Thank you :) – Andrew Gierens Oct 22 '12 at 01:57
-
@dana0550 You sir are an absolute legend! Thank you so much you have saved me weeks of trouble! – Andrew Gierens Oct 22 '12 at 12:15
-
@dana0550 How would I select the image with a specific date to be displayed in one row and the others in another row? For example if I wanted "10232012_19275917_image.jpg" to be displayed in row 0, and then "10232012_20303216_image.jpg" to be displayed in row 1? – Andrew Gierens Oct 23 '12 at 10:23
You can save the images as an NSData object inside an NSDictionary with Pictue Name as keys and whenever the app goes to the background the NSDictionary get's saved in an NSUserDefaults object later to be reloaded on app init.
In AppDelegate.m
-(void) applicationDidEnterBackground:(UIApplication*)application
{
NSUserDefaults *infoSaved = [NSUserDefaults standardUserDefaults];
[infoSaved setObject:imagesDictionary forKey:@"imagesFile"];
[infoSaved:synchronize];
}
This saves your NSDictionary in a file in the app folder on the device.
After taking a new picture from the camera, update your imageDictionary with the new image object"
in your viewController
-(void) updateImageDictionary {
NSData *imageNSData = UIImagePNGRepresentation(theUIImage);
[imagesDictionary addObject:imageNSData forKey:@"TheImageName"];
}
When you need the images list to be refreshed, probably in your app init, load them from this object in the NSUserDefaults:
in your viewController
-(void) loadImagesDictionary {
imagesDictionary = [infoSaved objectForKey:@"imagesFile"];
}
You also need to find a way to share the imagesDictionary object in your view controller with the imagesDictionary object in your AppDelegate. One way to do it is using Global Variables and a simpler one will be to use the NSUserDefault object.

- 1,110
- 9
- 22