Accessing and using the files in the app sandbox - ios

I have an iOS application in which I download some files from a remote server and store them in the app sandbox directory, Documents. I am sure the files are saved in the sandbox properly because when I run the following piece of code:
NSFileManager* fileManager = [NSFileManager defaultManager];
NSString* documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSError* error;
NSLog(#"%#",[fileManager contentsOfDirectoryAtPath:documentPath error:&error]);
I get the following output:
2014-07-09 17:39:07.768 Sample[13413:60b] (
"test.json",
"test.png"
)
However, I can not access these files in the Documents directory. I try to get the contents of test.json with the following code:
NSString* testJsonDir = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"json"];
NSString* testJson = [NSString stringWithContentsOfFile:testJsonDir encoding:NSUTF8StringEncoding error:&error];
This returns testJsonDir as nil and gives an error with code 258. Is there some other way to do this?

[NSBundle mainBundle] refers to the .app bundle, not the Documents directory. To access test.json, use this:
NSError *error = nil;
NSURL *documentsUrl = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0];
NSString *testJson = [NSString stringWithContentsOfURL:[documentsUrl URLByAppendingPathComponent:#"test.json"] encoding:NSUTF8StringEncoding error:&error];
I'm using -URLsForDirectory:inDomains: instead of NSSearchPathForDirectoriesInDomains() because former is a preferred way.

[NSBundle pathForResource:ofType:] will locate files within the app bundle, not the documents folder.
You want:
NSString *testJsonDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *testJsonFile = [testJsonDir stringByAppendingPathComponent:#"test.json"];
NSString *testJson = [NSString stringWithContentsOfFile:testJsonFile
encoding:NSUTF8StringEncoding
error:&error];

Related

Read/Write .string files from/to Directory

I have a framework that expects a .string file from the Project that it is imported to. How do I save a .string file from my app's [NSBundle mainBundle] to NSLibraryDirectory, and then have the framework read it from NSLibraryDirectory?
Thank you
Thanks #iOS_Developer for the writing part.
NSString *resourcepath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"filename.strings"];
NSString *filePath = [kSXBFileManLibraryDirectoryPath stringByAppendingPathComponent:#"filename.strings"];
Write:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
if ([fileManager copyItemAtPath: resourcepath toPath:destination error:&error]){
NSLog(#"Copy Success");
}
else{
NSLog(#"Copy error: %#", error);
}
Read:
NSString *newPath = [kLibraryDirectoryPath stringByAppendingPathComponent:#"filename.strings"];
NSDictionary *contents = [NSDictionary dictionaryWithContentsOfFile:newPath];
NSLog(#"contents:%#", [contents objectForKey:#"login.background"]);
where;
#define kLibraryDirectoryPath [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject]
filename.strings
"login.background" = "FE8100";
"login.textField" = "FE8100";
"login.button" = "1B0D62";
You can get path to bundle Directory and Library directory and Move file from bundle to Library directory with CopyItemAtPath
NSArray *libraryPath=NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *directoryPath = [libraryPath objectAtIndex:0];
NSString *imagePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"Templete.string"];
// Copy the image Folder from the package to the users filesystem
[fileManager copyItemAtPath:imagePathFromApp toPath:directoryPath error:nil];

How can I edit a file in app bundle?

In my app, I load data from a CSV file stored in the bundle resources. However, I'd like to be able to update this file programmatically when the user taps the Update button. Is there a way to change a resource in the app bundle programatically? Here is the code I use to access the file:
NSString *path = [[NSBundle mainBundle] pathForResource:#"query_result" ofType:#"csv"];
NSArray *rows = [NSArray arrayWithContentsOfCSVFile:path];
First of all load file from bundle and after that just store in Document directory then you can make change on this file again save on document directory to access changed file.
Use this code copy from mainbundle to Document.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dataPath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent:#"tessdata"];
NSLog(#"Datapath is %#", dataPath);
// If the expected store doesn't exist, copy the default store.
if ([fileManager fileExistsAtPath:dataPath] == NO)
{
NSString *tessdataPath = [[NSBundle mainBundle] pathForResource:#"eng" ofType:#"traineddata"];
[fileManager copyItemAtPath:tessdataPath toPath:dataPath error:&error];
}
-(NSString*) applicationDocumentsDirectory{
// Get the documents directory
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths objectAtIndex:0];
return docsDir;
}
And then get the Saved file to change...
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *fullPath = [[paths lastObject] stringByAppendingPathComponent:#"recentDownload.txt"];

View the contents of Custom Directory in iOS

I am creating a directory inside my application.Is there a code to view the contents of the directory in xcode. For example in android you can create a custom directory and view its contents using a file manager application. Can the similar procedure be done in apple?
Here is the code which i use to create a directory?
bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
fileManager = [NSFileManager defaultManager];
myImageDirectory = [fileManager URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask];
if ([myImageDirectory count] == 1){
NSLog(#"myImageDirectoryIs already present directory is already present");
}else{
directoryPath = [[myImageDirectory objectAtIndex:0] URLByAppendingPathComponent:bundleIdentifier];
NSLog(#"myImageDirectory directory name = %#",[directoryPath absoluteString]);
NSError *theError = nil;
if (![fileManager createDirectoryAtURL:directoryPath withIntermediateDirectories:NO attributes:nil error:&theError]){
NSLog(#"didnt write image data");
}else{
imagePath = [[directoryPath absoluteString] stringByAppendingPathComponent:[NSString stringWithFormat:#"/%#_%#_%#_image.jpg",dIdNo,iIdNo,[self currentDateandTime]]];
[imageData writeToFile:imagePath atomically:YES];
}
}
If your app is running in the simulator you'll need to use Finder. Go to the following directory:
/Users/<username>/Library/Application Support/iPhone Simulator/<iOS version>/Applications/<uuid>/Library/Application Support
If your app is running on the device you can use Xcode:
Connect the device
Choose menu option Window -> Organizer
Go to the Devices Tab
Click Applications under the device menu on the left
Pick your Application
The directory contents will be listed and you can optionally download everything.
try this...
to create a directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"/MyFolder"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error]; //Create folder
to retrieve contents from directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *customDirectory = [documentsDirectory stringByAppendingPathComponent:#"/MyFolder"];
NSError * error;
NSArray *directoryContents = [[NSFileManager defaultManager]
contentsOfDirectoryAtPath:customDirectory error:&error];
for(NSString *strFile in directoryContents)
{
NSString *strVideoPath = [NSString stringWithFormat:#"%#/%#",customDirectory,strFile];
if([[strVideoPath pathExtension] isEqualToString:#"mp4"] || [[strVideoPath pathExtension] isEqualToString:#"mov"])
{
[urlArray addObject:strVideoPath];
}
}
you can get the contents of the directory(MYNewFolder) from below code:
NSString *stringPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingPathComponent:#"MYNewFolder"];
NSArray *filePathsArray = [[NSFileManager defaultManager]
subpathsOfDirectoryAtPath:stringPath
error:nil];
for ( NSString *apath in filePathsArray )
{
NSLog(#"inside the file path array=%d",apath);
}
Method
-(NSArray *) getObjectsInDirectory:(NSString *)directory {
NSFileManager * fm = [NSFileManager defaultManager];
NSError * error = nil;
NSArray * result = [fm contentsOfDirectoryAtPath:directory error:&error];
return result;
}
How-To
NSString * documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSArray * files = [self getobjectsInDirectory:documentsPath];
This code is used to get an array of the files within the documents directory.
Viewing the Files
NSLog(#"%#", files);
Check this class out, it allows you to simplify so many things in iOS: Atomic Class

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).

-[NSString writeToFile:] does not change the contents of the file

I'm trying to write to a file "index.html" that I have in my resources. I can load the file with no problem, but I can't seem to write to it. Nothing is showing up as an error, it simply doesn't write. The app doesn't abort or anything, but when I re-load the file nothing has changed.
My writing code:
NSBundle *thisBundle = [NSBundle bundleForClass:[self class]];
NSString *path = [thisBundle pathForResource:#"index" ofType:#"html"];
NSString *myString = [[NSString alloc] initWithFormat:#""];
[myString writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:NULL];
My loading code:
[myWebView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"index" ofType:#"html"]isDirectory:NO]]];
What am I doing wrong?
The reason that your existing code doesn't overwrite the index.html file is that an application can not overwrite its resources. Apple's iOS Application Programming Guide specifically says:
This is the bundle directory containing the application itself. Do not write anything to this directory. To prevent tampering, the bundle directory is signed at installation time. Writing to this directory changes the signature and prevents your application from launching again.
Instead, write to your documents directory. You can get the path to the documents directory like this:
NSString * docsDir = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
Note that NSHomeDirectory() on iOS simple returns the path to your application's bundle. Once you have the path to the documents directory, you can write to a resource, let's say index.html, as follows:
NSString * path = [docsDir stringByAppendingPathComponent:#"index.html"];
[myString writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
Note that I changed your error: parameter to nil. This will not actually affect anything, but it is common practice to use nil to indicate NULL Objective-C objects.
Try to move your file to Documents Directory before perform the operation this bunch of code makes the work
.h
#import <Foundation/Foundation.h>
#interface NSFileManager (NSFileManagerAdds)
+ (NSString*) copyResourceFileToDocuments:(NSString*)fileName withExt:(NSString*)fileExt;
#end
.m
#import "NSFileManager + NSFileManagerAdds.h"
#implementation NSFileManager (NSFileManagerAdds)
+ (NSString*) copyResourceFileToDocuments:(NSString*)fileName withExt:(NSString*)fileExt
{
//Look at documents for existing file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.%#", fileName, fileExt]];
NSFileManager* fileManager = [NSFileManager defaultManager];
if(![fileManager fileExistsAtPath:path])
{
NSError *nError;
[fileManager copyItemAtPath:[[NSBundle mainBundle] pathForResource:fileName ofType:fileExt] toPath:path error:&nError];
}
return path;
}
#end
Finally you should use it in something like that:
[NSFileManager copyResourceFileToDocuments:#"index" withExt:#"html"];

Resources