save image to subfolder of /library/Application Support/bundleID_name/... iOS - ios

The following code works without error or exception - but still, it does not do what it should ! I wanted to save an image into the iOS library/Application Support folder. More precisely, the image should be placed into a /library/Application Support/bundleID_name/subfolder/ (and the subfolder being called "location1").
If I check the functionality with the iOS-Simulator, I can see the creation of the subfolder (i.e. .../library/Application Support/bundleID_name/location1/). Also the function "saveImage" works without exception. But there is no image being saved !!!! (i.e.the image-file is missing and the folder remains empty) !!
What could be the mistake ??
Here is my code with the call of two functions (see code below):
UIImage *in_image = [UIImage imageNamed:#"template009c.jpg"];
NSString *locDirectoryName = #"location1";
NSURL *LocationDirectory = [self appendLocationToApplicationDirectory:locDirectoryName];
[self saveImage:in_image :#"image1" :LocationDirectory];
With the corresponding function-Nr1:
- (NSURL*)appendLocationToApplicationDirectory:(NSString*)locationDirName
{
NSString* appBundleID = [[NSBundle mainBundle] bundleIdentifier];
NSFileManager*fm = [NSFileManager defaultManager];
NSURL* dirPath = nil;
// Find the application support directory in the home directory.
NSArray* appSupportDir = [fm URLsForDirectory:NSApplicationSupportDirectory
inDomains:NSUserDomainMask];
if ([appSupportDir count] > 0) {
// Append the bundle ID and the location-Foldername to the URL for the Application Support directory
dirPath = [[[appSupportDir objectAtIndex:0] URLByAppendingPathComponent:appBundleID] URLByAppendingPathComponent:locationDirName];
// If the directory does not exist, this method creates it.
// This method call works in OS X 10.7 and later only.
NSError* theError = nil;
if (![fm createDirectoryAtURL:dirPath withIntermediateDirectories:YES attributes:nil error:&theError]) {
// Handle the error.
NSLog(#"%#", theError.localizedDescription);
return nil;
}
else {
// Mark the directory as excluded from iCloud backups
if (![dirPath setResourceValue:#YES
forKey:NSURLIsExcludedFromBackupKey
error:&theError]) {
NSLog(#"Error excluding %# from iCloud backup %#", [dirPath lastPathComponent], theError.localizedDescription);
}
else {
NSLog(#"Location Directory excluded from iClud backups");
}
}
}
return dirPath;
}
And function Nr2:
//saving an image
- (void)saveImage:(UIImage*)image :(NSString*)imageName :(NSURL*)pathName {
NSData *imageData = UIImagePNGRepresentation(image); //convert image into .png format.
NSFileManager *fileManager = [NSFileManager defaultManager];
// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *LocationDirectory = [pathName absoluteString];
NSString *fullPath = [LocationDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.png", imageName]];
/***** THE FOLLOWING LINE DOES NOT SEEM TO DO WHAT IT IS SUPPOSED TO *******/
[fileManager createFileAtPath:fullPath contents:imageData attributes:nil];
/**** I also tried without the FileManager, but same problem - no file written... ***/
// [imageData writeToFile:fullPath atomically:NO];
NSLog(#"image saved");
}
By the way, getting the "fullPath" with the XCode-Debugger, I get:
"fullPath NSPathStore2 * #"file:/Users/username/Library/Application%20Support/iPhone%20Simulator/7.1/Applications/2BCC3345-9M55F-4580-A1E7-6694E33456777/Library/Application%20Support/bundleID_name/image1.png" 0x09d50950
Doesn't that also seem correct ?? But why is [fileManager createFileAtPath:fullPath contents:imageData attributes:nil]; not performing ???

This:
"fullPath NSPathStore2 * #"file:/Users/username/Library/Application%20Support/iPhone%20Simulator/7.1/Applications/2BCC3345-9M55F-4580-A1E7-6694E33456777/Library/Application%20Support/bundleID_name/image1.png" 0x09d50950
is not a valid path, it's a URL path but stored in a string. If you are going to use URL's then use ULRs rather than trying to convert to a string:
[imageData writeToURL:pathName atomically:YES];
(preferably naming the parameter as pathURL) and if you want to use paths then don't use a URL at any stage.
Also, where an API method returns an error or status flag, check it in the code as standard.

I'm pretty sure you can't save an image on a path you specify. You can save images on the gallery or in DocumentDirectory. This should be the code to save an image on the DocumentDirectory:
NSString *imgName=[#"imgname.png"];
[[NSUserDefaults standardUserDefaults]setValue:imgName forKey:#"imageName"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDirectory stringByAppendingPathComponent:imgName];
UIImage *image = imageView.image; // imageView is my image from camera
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:savedImagePath atomically:NO];

Related

How to access a directory

I would like to save image in a folder. I already the code. to download and save image but I would like to know how to find the path of ma folder !
I create a directory in xcode but the images don't find it and there aren't image in it.
So, I would like to save images in "img_bkgrd" folder.
[UIImageJPEGRepresentation(image, 1.0) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#", imageName]] options:NSAtomicWrite error:nil];
to use the image I use this method:
-(UIImage *) loadImage:(NSString *)fileName inDirectory:(NSString *)directoryPath{
UIImage * result = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:#"%#/%#", directoryPath, fileName]];
return result;
}
Can you send me the correct path ?
thanks
You can't save the images there. First of all, this is not actually a folder. It is called a group. It is a part of application bundle, which is readonly. You need to save data into Documents directory. Something like that:
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *imageFolderPath = [documentsDirectory stringByAppendingPathComponent:#"/img_bckr"];
if (![[NSFileManager defaultManager] fileExistsAtPath:imageFolderPath])
[[NSFileManager defaultManager] createDirectoryAtPath:imageFolderPath withIntermediateDirectories:NO attributes:nil error:&error];
NSString* imagePath = [imageFolderPath stringByAppendingPathComponent:#"MyImage"];
[UIImageJPEGRepresentation(image, 1.0) writeToFile:imagePath options:NSAtomicWrite error:nil];
You may store imagePath somewhere or build it later based upon file name and then simply:
UIImage* img = [UIImage imageWithContentsOfFile:imagePath];

Imagepath Replace in Document Directory

For using NSFileManager, if exists the Image path or folder,how to replace new image path (or) Folder in document directory .
Is there the replace feature in NSFileManager?
(how to replace image path position with new image path in document directory)
You want to owerwrite an image, just write it to file.
If an image with the same name exists at the same path, it will be overwritten:
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
UIImage * imageToSave = [UIImage imageNamed:#"Icon.png"];
NSData * binaryImageData = UIImagePNGRepresentation(imageToSave);
[binaryImageData writeToFile:[basePath stringByAppendingPathComponent:#"myfile.png"] atomically:YES];
You can not replace a path using NSFileManager because, you've already saved ImagePath. Now you can check if that path is exists then you can remove that filePath using this:
if ([fileManager fileExistsAtPath:Path] == YES) {
[fileManager removeItemAtPath:Path error:&error];
}
Now save your new path.
If you want to replace content then simple remove first then write again using
writeToFile:filePath
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* foofile = [documentsPath stringByAppendingPathComponent:filename];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:foofile];
NSLog(fileExists ? #"Yes" : #"No");
if (fileExists == YES)
{
NSString *filePath = [NSString stringWithFormat:#"%#/%#", aDocumentsDirectory,filename];
NSData *data1 = [NSData dataWithData:UIImagePNGRepresentation(image)];
[data1 writeToFile:filePath atomically:YES];
}

Managing files and directories in an app's Documents directory

I am trying to work out how to manage files and directories in my app's Documents folder. I have been trying to make sense of the NSData class but without joy. I have managed to write an image to my Documents folder using the following code.
- (IBAction)writeImage:(id)sender
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDirectory stringByAppendingPathComponent:#"savedImage.png"];
UIImage *image = [UIImage imageNamed:#"Default.png"];
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:savedImagePath atomically:NO];
}
What I would like to know is how to create and delete directories and files. Can anyone point me to correct place to look? Thanks in advance.
For folder you can use:
[[NSFileManager defaultManager] createDirectoryAtURL:folder withIntermediateDirectories:YES attributes:nil error:&error];
It will create all folders at given path which is cool :)
The NSFileManager class enables you to perform many generic file-system operations and insulates an app from the underlying file system.
There is a class method in NSFileManager class called +defaultManager which always gives you same FileManager object or shared Object and most file operations can be performed using this shared file manager object.
You can write by avoiding overwriting your file if it already exists as below and can also check if the folder is writable or not.
NSString *imageName = #"Default.png";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *savedImagePath = [NSString stringWithFormat:#"%#/%#", documentsDirectoryPath, imageName];
// Write only if file does not exist.
if (![[NSFileManager defaultManager] fileExistsAtPath:savedImagePath]) {
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:savedImagePath atomically:NO];
}
// Check if folder is writable
NSString *folderPath = #"someFolderPath";
if ([[NSFileManager defaultManager] isWritableFileAtPath:folderPath]) {
NSLog(#"Folder is writable");
}else {
NSLog(#"Folder is not writable");
}

Delete image from app directory in iPhone

I want to delete an image from my iPhone app.
I use the method below, passing the name of the image as an argument.
The problem is that the image isn't deleted.
- (void)removeImage:(NSString*)fileName {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithFormat:#"%#.png", fileName]];
[fileManager removeItemAtPath: fullPath error:NULL];
NSLog(#"image removed: %#", fullPath);
NSString *appFolderPath = [[NSBundle mainBundle] resourcePath];
NSLog(#"Directory Contents:\n%#", [fileManager directoryContentsAtPath: appFolderPath]);
}
The last two lines show the content in my app directory and the image I want to delete is still there. What am I doing wrong?
You are trying to delete a file in the Documents directory. You then read the contents of the bundle resources directory. These are not the same directory.
If you're trying to delete a file in the Documents directory, the you should rad that directory in your NSLog() at the end. If you're trying to delete a file inside your bundle, this is impossible. App bundles are signed and cannot be modified.
your code looks ok, so try adding some 'NSError' object to you code:
- (void)removeImage:(NSString*)fileName {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithFormat:#"%#.png", fileName]];
NSError *error = nil;
if(![fileManager removeItemAtPath: fullPath error:&error]) {
NSLog(#"Delete failed:%#", error);
} else {
NSLog(#"image removed: %#", fullPath);
}
NSString *appFolderPath = [[NSBundle mainBundle] resourcePath];
NSLog(#"Directory Contents:\n%#", [fileManager directoryContentsAtPath: appFolderPath]);
}
In the code above I passed a NSError the error parameter of removeItemAtPath. If the system can't delete the file, this method will return NO and fill the error object with the error raised.
Based on your comment I found out that you are trying to delete the default.png and replace it with another one. Unfortunately, this is impossible. The image default.png is a part of your application bundle, which cannot be modified once it has been created and signed (this is a security measure from Apple, so applications cannot change after they have been reviewed). The only locations where you can create and delete files is inside the sandbox given to your application (the Documents folder).

iPhone UIImage - Data Persistance

Simple question regarding data persistance between application sessions.
My application allows the user to select an image from the Library using a UIImagePickerController. The selected photo is then used as the background to the application.
As the UIImagePickerController delegate method actually returns an image as opposed to an image path, I am wondering what is the best way to persist this image over user sessions?
I do not require any other data to be persisted at the moment, as everything else is pulled in from SQL Server, but I do not want the added overhead of having to store the image in the server as well, which would mean that everytime the user opened the application the background image would first have to be downloaded from the server into a byte array and then converted into an image.
I have found the following code that can save the image:
- (void)saveImage:(UIImage *)image withName:(NSString *)name {
//save image
NSData *data = UIImageJPEGRepresentation(image, 1.0);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
[fileManager createFileAtPath:fullPath contents:data attributes:nil];
}
I am not on a mac at the moment, so I cannot test this code, but I have a couple of questions regarding the code above:
I don't want a lot of files cluttering the file system. So I would like a single background file (background.png); how would the code above handle a situation where this file already existed?
Would it overwrite the existing file or would it throw an error?
How would I go about loading the image again?
You have to remove the file first:
- (void)saveImage:(UIImage *)image withName:(NSString *)name {
//save image
NSData *data = UIImageJPEGRepresentation(image, 1.0);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
NSError *error = nil;
if( [fileManager fileExistsAtPath:fullPath] ){
if( ! [fileManager removeItemAtPath:fullPath error:&error] ) {
NSLog(#"Failed deleting background image file %#", error);
// the write below should fail. Add your own flag and check below.
}
}
[data writeToFile:fullPath atomically:YES];
}
Reading back in should work as follows:
...
UIImage *bgImage = [UIImage imageWithContentsOfFile:fullPath];
...

Resources