How can I load only the latest saved image from the document directory? - objective-c

I would like to show the latest added image that I saved into my document directory.
In the code below I tried to first count all the images that are in ImageData.plist and then show the latest image by subtracting 1.
It doesn't show any image so I am doing something wrong, but can't figure out what exactly?
Thx in advance.
- (void)viewDidLoad {
[super viewDidLoad];
//Show latest added image from document directory
//Add UIImageView
UIImageView *guideSheet = [[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 768, 1024)]autorelease];
//Add latest image
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"ImageData.plist"];
NSArray *plistFile = [[NSArray alloc] initWithContentsOfFile:path];
NSInteger plistCount = [plistFile count];
for (NSInteger i = plistCount; i < (plistCount - 1); i++) {
// Show image
NSString *imageName = [NSString stringWithFormat:#"ImageData/ImageData%i.jpg", i];
UIImage* content = [UIImage imageWithContentsOfFile:imageName];
guideSheet.image = content;
[self.view addSubview:guideSheet];
}
[plistFile release];
}

When you created the NSString object imageName, you did not append the documents directory location. Therefore, the full path of the image it's using is /ImageData/ImageData%i.jpg.
NSString *imageName = [documentsDirectory stringByAppendingPathComponent:#"ImageData/ImageData%i.jpg", i];
Should work if you were able to save the images correctly into the documents directory (if these images are in the mainBundle, then you'll have to use pathForResource instead of the above).

Related

How to get path for images objective-C

I want to call images from different folder, would you please help me to implement this;
I have this structure for my folders :
Folder1
file1
image1.jpg
file2
image2.jpg
file3
image3.jpg
Folder2 ....
inside of each file%d I have one image%.jpg
I want to call my images in loop,
for (i = 1; i > image; i++)
{
NSString *image = [NSString stringWithFormat:#"image%d.jpg", i];
But my question is how to enter to the folders and get images
can I have something like this :
stringWithFormat:#"Folder%d/File%d/image%d" ofType:#"jpg"
what is the best way?
Thanks in advance!
Here are a few useful code snippets that work for me.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *mapDirPath = [documentsDirectory stringByAppendingPathComponent:#"/MapCache"];
// Creating a directory in the documents directory
NSError* error;
if (![[NSFileManager defaultManager] fileExistsAtPath:mapDirPath])
[[NSFileManager defaultManager] createDirectoryAtPath:mapDirPath withIntermediateDirectories:NO attributes:nil error:&error];
// loading an image
NSString *filePath = [self.localImagePath stringByAppendingPathComponent: key];
if ( [[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
UIImage* image = [UIImage imageWithContentsOfFile:filePath];
return image;
}
// Writing an image
[[NSFileManager defaultManager] createFileAtPath:filePath contents:remoteData attributes:nil];
Hope that helps
Of course, if you're reading images from your bundle, you want this instead
[[NSBundle mainBundle] pathForResource: #"filename" ofType:#"png" directory: #"directory1"]
Right, this is how I would do it.
for (f = 1; f <= numberOfFolders; i++) {
for (i = 1; i <= numberOfImages; i++) {
NSString* file = [NSString stringWithFormat: #".../Folder%d/File%d/image%d.jpg", f, i, i];
NSImage* image = [NSImage imageNamed: file];
// Do something with the image
}
}
A note: I don't know where Folder1/Folder2... etc are, so I used '.../' on the code. Be sure to fill that part appropriately.
Iterate folders and images appending the image path to the library path:
NSString * libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
for (NSUInteger f = 1; f <= numFolders; i++) {
for (NSUInteger i = 1; i <= numImages; i++) {
// Create the image path
NSString * imagePath = [NSString stringWithFormat:#"%#/Folder%d/File%d/image%d.jpg", libraryPath, f, i, i];
// Check if file exists
if ( [[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
UIImage * image = [UIImage imageWithContentsOfFile:imagePath];
// Use image...
}
else {
NSLog(#"Image not found.");
}
}
}

How Can I Save This Array of Images?

I'm very new to programming, and I jumped right into a project (I know thats not the smartest thing to do, but I'm learning as I go). The app that I'm writing has 10 UIImageViews that display a picture from the users camera roll. The code I'm using needs each of the UIImageViews to have tags. I'm currently using NSData to save the array images, and it works great, but I can't use this method anymore because NSData doesn't support the use of tags. I also can't use NSUserDefaults, because I can't save images to a plist. Here is how I'm attempting to do this (using the NSData method, which works but I have to edit this so that my tags work.)
This is my current code:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
if (imageView.image == nil) {
imageView.image = img;
[self.array addObject:imageView.image];
[picker dismissModalViewControllerAnimated:YES];
[self.popover dismissPopoverAnimated:YES];
return;
}
if (imageView2.image == nil) {
imageView2.image = img;
NSLog(#"The image is a %#", imageView);
[self.array addObject:imageView2.image];
[picker dismissModalViewControllerAnimated:YES];
[self.popover dismissPopoverAnimated:YES];
return;
}
...
- (void)applicationDidEnterBackground:(UIApplication*)application {
NSLog(#"Image on didenterbackground: %#", imageView);
[self.array addObject:imageView.image];
[self.array addObject:imageView2.image];
[self.user setObject:self.array forKey:#"images"];
[user synchronize];
}
- (void)viewDidLoad
{
self.user = [NSUserDefaults standardUserDefaults];
NSLog(#"It is %#", self.user);
self.array = [[self.user objectForKey:#"images"]mutableCopy];
imageView.image = [[self.array objectAtIndex:0] copy];
imageView2.image = [[self.array objectAtIndex:1] copy];
UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:app];
[super viewDidLoad];
}
Any help or suggestions on how to edit this code so that I can save the images, while using tags is much appreciated, thanks!
EDIT: Here is my updated code:
-(IBAction)saveButtonPressed:(id)sender {
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES) objectAtIndex:0];
for (UIImageView *imageView in self.array) {
NSInteger tag = self.imageView.tag;
UIImage *image = self.imageView.image;
NSString *imageName = [NSString stringWithFormat:#"Image%i.png",tag];
NSString *imagePath = [docsDir stringByAppendingPathComponent:imageName];
[UIImagePNGRepresentation(image) writeToFile:imagePath atomically:YES];
}
NSLog(#"Saved Button Pressed");
}
- (void)applicationDidEnterBackground:(UIApplication*)application {
}
-(void)viewDidLoad {
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) objectAtIndex:0];
NSArray *docFiles = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:docsDir error:NULL];
for (NSString *fileName in docFiles) {
if ([fileName hasSuffix:#".png"]) {
NSString *fullPath = [docsDir stringByAppendingPathComponent:fileName];
UIImage *loadedImage = [UIImage imageWithContentsOfFile:fullPath];
if (!imageView.image) {
imageView.image = loadedImage;
} else {
imageView2.image = loadedImage;
}
}
}
}
You need to use "Fast Enumeration" to parse the array's objects, and write each object to disk sequentially. First, you're going to need to add the UIImageView objects to the array instead of the UIImage property of the UIImageView, so you can recover the tag. So instead of writing
[self.array addObject:imageView.image];
It will be
[self.array addObject:imageView];
Try to follow along with my code. I inserted comments on each line to help.
-(void)applicationDidEnterBackground:(UIApplication *)application {
//Obtain the documents directory
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainmask,YES) objectAtIndex:0];
//begin fast enumeration
//this is special to ObjC: it will iterate over any array one object at a time
//it's easier than using for (i=0;i<array.count;i++)
for (UIImageView *imageView in self.array) {
//get the imageView's tag to append to the filename
NSInteger tag = imageView.tag;
//get the image from the imageView;
UIImage *image = imageView.image;
//create a filename, in this case "ImageTAGNUM.png"
NSString *imageName = [NSString stringWithFormat:#"Image%i.png",tag];
//concatenate the docsDirectory and the filename
NSString *imagePath = [docsDir stringByAppendingPathComponent:imageName];
[UIImagePNGRepresentation(image) writeToFile:imagePath atomically:YES];
}
}
To load the images from disk, you'll have to look at your viewDidLoad method
-(void)viewDidLoad {
//get the contents of the docs directory
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainmask,YES) objectAtIndex:0];
//Get the list of files from the file manager
NSArray *docFiles = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:docsDir error:NULL]);
//use fast enumeration to iterate the list of files searching for .png extensions and load those
for (NSString *fileName in docFiles) {
//check to see if the file is a .png file
if ([fileName hasSuffix:#".png"]) {
NSString *fullPath = [docsDir stringByAppendingPathComponent:fileName];
UIImage *loadedImage = [UIImage imageWithContentsOfFile:fullPath];
//you'll have to sort out how to put these images in their proper place
if (!imageView1.image) {
imageView1.image = loadedImage;
} else {
imageView2.image = loadedImage;
}
}
}
}
Hope this helps
One thing you need to be aware of is that when an app enters the background it has about 5 seconds to clean up its act before it's suspended. The UIPNGRepresentation() function takes a significant amount of time and is not instantaneous. You should be aware of this. It would probably be better to write some of this code in other places and do it earlier than at app backgrounding. FWIW
You can use the [NSbundle Mainbundel] to store that images.
To get path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
First, there's still a problem in your for loop.
for (UIImageView *imageView in self.array) {
NSInteger tag = self.imageView.tag;
UIImage *image = self.imageView.image;
// ...
}
Before you make any other changes, you must understand why. imageView is your for loop control variable, which changes on each iteration through the loop. self.imageView is a different thing. It is the first of the 10 imageViews attached to your viewController. Every time this loop cycles, it looks at the first imageView, and only the first.
As for why saving doesn't work, it's probably because the arrays elsewhere aren't working. Add some logging to make sure there's something in the array, and that it has as many elements as you expect.
-(IBAction)saveButtonPressed:(id)sender {
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES) objectAtIndex:0];
// Log to make sure the views expected have previously been stored.
// If the array is empty, or shorter than expected, the problem is elsewhere.
NSLog(#"Image view array before saving = %#", self.array);
for (UIImageView *imageViewToSave in self.array) {
NSInteger tag = imageViewToSave.tag;
UIImage *image = imageViewToSave.image;
NSString *imageName = [NSString stringWithFormat:#"Image%i.png",tag];
NSString *imagePath = [docsDir stringByAppendingPathComponent:imageName];
// Log the image and path being saved. If either of these are nil, nothing will be written.
NSLog(#"Saving %# to %#", image, imagePath);
[UIImagePNGRepresentation(image) writeToFile:imagePath atomically:NO];
}
NSLog(#"Save Button Pressed");
}

Displaying images in tableview

I didnt get any images displayed, only the filename is shown.
Currently im using this codes:
NSString *filePath = [[self documentsPath] stringByAppendingPathComponent:#""];
NSFileManager *imagesFileManager = [NSFileManager defaultManager];
imagesArr = [[imagesFileManager contentsOfDirectoryAtPath:filePath error:nil]filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"self ENDSWITH '.jpg'"]];
arryList = [[NSMutableArray alloc] initWithArray:[imagesArr copy]];//display text
imagesList = [[NSMutableArray alloc]init];//display image
for (NSString *anImage in arryList) {
anImage = [NSString stringWithFormat:#"Documents/%#",anImage];
[imagesList addObject:anImage];
}
In the for loop , you are just adding the file path to the array instead of UIImage.
Change the for loop as follows:
NSString *docPath = [self documentsPath];
for (NSString *anImagePath in arryList) {
anImagePath = [NSString stringWithFormat:#"%#/%#",docPath,anImagePath];
UIImage *image = [UIImage imageWithContentsOfFile:anImagePath];
if ( image )
[imagesList addObject:image];
}

A function to write data to plist in Objective-c

Suppose I have a custom function called savePlist as below.
CommonClass.m
- (NSString *)getDirectoryPath
{
NSArray *pathList = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [pathList objectAtIndex:0];
return path;
}
- (void)savePlist:(NSString *)fileName WithArray:(NSArray *)fileArr
{
NSString *path = [[self getDirectoryPath] stringByAppendingPathComponent:fileName];
[fileArr writeToFile:path atomically:YES];
}
While I run a code as below, no plist is generated.
ABCAppDelegate.m
...
[cc savePlist:#"example.plist" WithArray:[NSArray new]];
The file of example.plist has not been generated, is there any mistakes on my code?
Thanks
UPDATE:
If I use the code as below, the xxx.plist file has been generated successfully.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *plistFile = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"abc.plist"];
NSMutableDictionary *plist = [[NSMutableDictionary alloc] initWithContentsOfFile:plistFile];
if (!plist) {
plist = [NSMutableDictionary new];
[plist writeToFile:plistFile atomically:YES];
NSLog(#"write plist");
}
Reference: link
UPDATE 2:
I change the code as below:
NSLog(#"code");
[cc savePlist:#"example.plist" WithArray:[NSArray new]];
NSLog(#"code");
- (void)savePlist:(NSString *)fileName WithArray:(NSArray *)fileArr
{
NSLog(#"fileName = %#, fileArr = %#", fileName, fileArr);
NSString *path = [[self getDirectoryPath] stringByAppendingPathComponent:fileName];
NSLog(#"path = %#", path);
[fileArr writeToFile:path atomically:YES];
}
It just print out:
2011-10-10 14:24:00.560 ABC[3390:207] code
2011-10-10 14:24:00.561 ABC[3390:207] code
No message of fileName = and fileArr =, also path = print out on the log, so the code inside savePlist have not been executed?
It looks like your common class object is not instantiated, and you are sending all those messages to nil. Try logging cc in your app delegate code, where you call this method from.
You need to create an instance of your common class, something like
cc = [[CommonClass alloc] init];
(may vary depending on your set up).

Inverted images in the simulator

I have a bit of simple code, that pulls images from the documents directory.. and loads it into an imageView.
- (void)viewDidLoad
{
[super viewDidLoad];
NSString* pathToFile = [NSString stringWithFormat:#"%#/images/%#",[self documentsDirectory],#"copy.jpg"];
UIImageView *tmp = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:pathToFile]];
[self.view addSubview:tmp];
}
- (NSString *)documentsDirectory
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [paths objectAtIndex:0];
}
My image, when viewed shows up correct, but when it's loaded into the app and viewed on the simulator.. it's inverted.
Example: https://skitch.com/critz/fnh8p/colorsnapper
any ideas, suggestions.. would be /greatly/ appreciated..
Interesting... Same code base run in >4.2 and the images are inverted. If I run it in the 5bx simulator.. they come out as they should.. SMH. Oh well..