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"];
Related
I am implementing setting bundle first time and I have done it by creating Root.plist and Child.plist in Settings.bundle and have some fields in these plist.
I need to update the fields (add or remove) of Child.plist according to web services and I have written code for that in appdelegate. Its working fine in simulator (all fields are updated accordingly) but its not working in device.
Can any one suggest me what could be the reason of it.
code to copy plist to document directory and update that (as per the asnwer)
NSString *bundle = [[NSBundle mainBundle]pathForResource:#"Settings" ofType:#"bundle"];
NSString *path = [bundle stringByAppendingPathComponent:#"Category.plist"];
NSMutableDictionary *dictOfPlist = [NSDictionary dictionaryWithContentsOfFile:path];
NSMutableArray *dictArray = [dictOfPlist valueForKey:#"PreferenceSpecifiers"];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path1 = [documentsDirectory stringByAppendingPathComponent:#"Child.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path1])
{
[fileManager copyItemAtPath:path toPath: path1 error:&error];
}
for (some condition)
{
// creating dictionary
// add dictionary to array dictArray
}
[dictOfPlist setObject:dictArray forKey:#"PreferenceSpecifiers"];
[dictOfPlist writeToFile:path1 atomically:YES];
I think you have a problem to write your PLIST. You need to copy your PLIST from your resources bundle into the documents directory and modify the PLIST inside this folder.
For that you can use this piece of code :
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"data.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#”data” ofType:#”plist”];
[fileManager copyItemAtPath:bundle toPath: path error:&error];
}
Have a look here.
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).
I m able to save the plist file in Simulator but I m not able to save the Plist file in the device. Any suggestion.
I m using
NSString* dictPath = [[NSBundle mainBundle] pathForResource:#"Dictionary" ofType:#"plist"];
NSDictionary * dict = [[NSDictionary alloc] initWithContentsOfFile:dictPath];
to read the files
and
[dict writeToFile:dictPath atomically: YES];
to write to file.
You can not write in to main bundle. You only can read from main bundle. If you want to write an file you need to place it in to the documents directory of your app.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.plist",plistName]];
If you need the plist from the main bundle you can copy it first in to the documents directory then modify it. It is advised to have a check to ensure it is copied only once.
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.plist",plistName]];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path]){
NSLog(#"File don't exists at path %#", path);
NSString *plistPathBundle = [[NSBundle mainBundle] pathForResource:plistName ofType:#"plist"];
[fileManager copyItemAtPath:plistPathBundle toPath: path error:&error];
}else{
NSLog(#"File exists at path:%#", path);
}
Generally you would store these in ~/Documents or in ~/Library depending on the file. The question What is the documents directory (NSDocumentDirectory)? includes the documentation links and sample code you need to understand this.
You need to save the plist in Documents directory
to write
NSString *mainBundlePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *dictPath = [mainBundlePath stringByAppendingPathComponent:#"Dictionary"];
NSDictionary * dict = ...; //Construct your dictionary
[dict writeToFile:dictPath atomically: YES];
to read
NSDictionary * dict = [[NSDictionary alloc] initWithContentsOfFile:dictPath];
Is it possible to write new file to bundle resource directory in iOS app?
No there is no way to write in the bundle dir.. because the bundle dir is code signed with SSL certificate and you can't break it. however you can easily write in the documents directory of you iphone application
You can get the documents directory path using this -
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
return [paths objectAtIndex:0];
Or you can copy the resources needed and then operate on files with writing permission.
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = dirPaths[0];
NSString *databasePath = [documentsDir stringByAppendingString:#"/TwigitDatabase.db"];
NSFileManager *fm = [NSFileManager defaultManager];
if(![fm fileExistsAtPath:databasePath]) { // Checking whether the my database was copied earlier, though it could be saved in some preferences property.
NSError *error;
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"TwigitDatabase" ofType:#"db"];
[[NSFileManager defaultManager] copyItemAtPath:soundFilePath toPath:databasePath error:&error];
NSLog(#"%#", error);
}
I have this code below:
NSString *fileName = [[NSUserDefaults standardUserDefaults] objectForKey:#"recentDownload"];
NSString *fullPath = [NSBundle pathForResource:fileName ofType:#"txt" inDirectory:[NSHomeDirectory() stringByAppendingString:#"/Documents/"]];
NSError *error = nil;
[textViewerDownload setText:[NSString stringWithContentsOfFile:fullPath encoding: NSUTF8StringEncoding error:&error]];
textviewerdownload is the textview displaying the text from the file. The actual file name is stored in an NSUserDefault called recentDownload.
When I build this, I click the button which this is under, and my application crashes.
Is there anything wrong with the syntax or just simple error?
The NSBundle class is used for finding things within your applications bundle, but the Documents directory is outside the bundle, so the way you're generating the path won't work. Try this instead:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *fullPath = [[paths lastObject] stringByAppendingPathComponent:#"recentDownload.txt"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *myPathDocs = [documentsDirectory stringByAppendingPathComponent:#"myfile.txt"];
if (![[NSFileManager defaultManager] fileExistsAtPath:myPathDocs])
{
NSString *myPathInfo = [[NSBundle mainBundle] pathForResource:#"myfile" ofType:#"txt"];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager copyItemAtPath:myPathInfo toPath:myPathDocs error:NULL];
}
//Load from File
NSString *myString = [[NSString alloc] initWithContentsOfFile:myPathDocs encoding:NSUTF8StringEncoding error:NULL];
This worked for me
Anyway, thank you all..
For read/write from text file check this url.