I am trying to create a plist file that I will write to later in my app. In the first viewDidLoad I call the following method
-(void)createFavoritesFile{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentDBFolderPath = [documentsDirectory stringByAppendingPathComponent:#"data.plist"];
if (![fileManager fileExistsAtPath:documentDBFolderPath])
{
NSLog(#"file doesnt exist");
NSString *resourceDBFolderPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"data.plist"];
[fileManager copyItemAtPath:resourceDBFolderPath toPath:documentDBFolderPath error:&error];
}
else{
NSLog(#"file exists");
}
}
However every time I run the app, I cannot find a file created, and if I close the app and reopen, NSLog shows that file doesnt exist again. Am I missing something?
You're ignoring the return value and error from -copyItemAtPath:toPath:error:. I'm willing to bet that call is returning NO and populating some error. You should check the return value of that and print out the error if it returns NO.
One possible reason why this is failing is you might not actually have a Documents folder yet, for some reason. You can ask NSFileManager to create it for you.
Print your resource path and see if the file exists in there. If so, but not working check this question: Working with paths from [[NSBundle mainBundle] resourcePath]
Anyway, if your resource is in your main bundle you can always use:
- (NSString *)pathForResource:(NSString *)name ofType:(NSString *)extension
Related
I have a Settings.plist file in my iOS application. I access it using this code below:
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Settings.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"Settings" ofType:#"plist"];
[fileManager copyItemAtPath:bundle toPath: path error:&error];
}
NSMutableDictionary *savedStock = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
But, say I make some changes to the Settings.plist file in my application, like add another row. Then if I publish it, users that already have my app will have an out dated Settings.plist file. Any ideas on a workaround or anything? I have tried accessing the Settings.plist file straight from the NSString *bundle, but then the values don't "save".
You need to do a file modification date check, see my answer here. Then if the modification date is later than the last checked date, download the Settings.plist file and replace it in the users app.
I've been writing this app for iPhone and I need to use sqlite. I have pre-loaded my sqlite with a bunch of data, I copied that sqlite file into my project folder. And when I launch the app, it seems like the sqlite data file was not copied to the simulator's app file (the document place). Here's my code:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *dbPath = [documentsDir stringByAppendingPathComponent:#"moviedbl.data"];
BOOL success = [fileManager fileExistsAtPath:dbPath];
if(!success){
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: #"moviedbl.data"];
//NSString *defaultDBPath = [[NSBundle mainBundle] pathForResource:#"moviedbl" ofType: #"data"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if(!success){
NSAssert1(0, #"Failed to create writable database file with message '%'.", [error localizedDescription]);
}
}
It seems that defaultDBPath refers to the app folder in the simulator, which originally does not contain any sqlite file, and instead, is actually waiting for a sqlite file to be copied to it. From what I understand, to copy the file, we should get the file from our bundle (not sure if bundle refers to our project folder or what, but I assumed it is our project folder) and copy it to our simulator. I've been stuck on this for days, please enlighten me... Thankyou very much in advance!!!
UPDATE:
So I actually got it working after all. At first I thought it was because I didn't copy the files from mainBundle or something, but it turns out that I did when I opened the actual folder of the .app in the path. I saw that the database it actually included. Something weird is that it doesn't have a file type, but in xCode it shows the file type as "data", so I kept using ofType: #"data". So in the end I changed it to ofType: #"" and it worked! Anyways! stupid me, but thanks for everyone who tried to help!! :D
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *dbPath = [documentsDir stringByAppendingPathComponent:#"moviedbl.data"];
if([fileManager fileExistsAtPath:dbPath]==NO){
NSString *defaultDBPath = [[NSBundle mainBundle] pathForResource:#"moviedbl" ofType: #"data"];
BOOL success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if(!success){
NSAssert1(0, #"Failed to create writable database file with message '%'.", [error localizedDescription]);
}
}
I have created a screen using Objective-C in an iPhone project. In that, there are 2 buttons (say A and B). On the click of button A, one xml file will be created in a folder (say INBOX).
My problem is, I need to create the file only if it does not exist at folder INBOX.
How can I do this? Can any one tell me the syntax?
Can you Please Check NSFileManager.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *pathForFile;
if ([fileManager fileExistsAtPath:pathForFile]){
}
try this:
- (BOOL)checkAndCopy {
NSError **error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"yourFile.xml"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
// this copy an existing xml (empty?) file from main bundle:
// try else to create a new file
NSString *bundle = [[ NSBundle mainBundle] pathForResource:#"yourFile" ofType:#"xml"];
[fileManager copyItemAtPath:bundle toPath:path error:error];
return YES;
}
return NO;
}
There have been similar questions on SO before:
This answer is probably most appropriate for you
Link to the NSFileManagerAPI
I current have everything setup to read from the documents directory and write to it , but Cannot do it because the file doesnt exist yet.
How is a file created within the code?
If you already have a template version of the document in your application's bundle then you should be able to write it to the application's document directory using something similar to the following. I haven't tested this code so I've probably got a few things wrong but that's the general idea.
- (void) applicationDidFinishLaunching {
NSArray* directories = NSSearchPathsForDirectoriesInDomain(NSDocumentsDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [directories objectAtIndex: 0];
NSString* path = [documentsDirectory stringByAppendingPathComponent: #"Something.plist"];
if (![[NSFileManager sharedInstance] fileExistsAtPath: path]) {
NSString* infoTemplatePath = [[NSBundle mainBundle] pathForResource: #"Something" ofType: #"plist"];
NSDictionary* info = [NSDictionary dictionaryWithContentsOfFile: infoTemplatePath];
[info writeToFile: path];
}
}
Use NSFileManger's fileExistsAtPath: to see if the file exist. If not create it before going on to the code that requires the file.
This one works better for me:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentDBFolderPath = [documentsDirectory stringByAppendingPathComponent:#"*.db"];
if (![fileManager fileExistsAtPath:documentDBFolderPath])
{
NSString *resourceDBFolderPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"*.db"];
[fileManager copyItemAtPath:resourceDBFolderPath toPath:documentDBFolderPath error:&error];
}
I want to read/write to cache.plist
If I want to read an existing premade plist file stored in the resources folder I can go:
path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathWithComponent#"cache.plist"];
NSMutableDictionary *root = ...
But then I wish to read it from the iPhone.
Can't, the Resources folder is only readable.
So I need to use:
NSDocumentDirectory, NSUserDomain,YES
So how can I have my plist file preinstalled to the Document Directory location?
Thus meaning I don't have to mess around with untidy code copying the plist file over at startup. (Unless that's the only way).
I know this isn't really what you're after, but as far as I know the only way to get the document into the Documents folder IS to actually copy it there...but only on the first startup. I'm going something similar for a sqlite database. Code is below, it works but please note it could do with a little bit of cleaning up:
// Creates a writable copy of the bundled default database in the application Documents directory.
- (void)createEditableCopyOfDatabaseIfNeeded {
// First, test for existence.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"WordsDatabase.sqlite3"];
createdDatabaseOk = [fileManager fileExistsAtPath:writableDBPath];
if (createdDatabaseOk) return;
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"WordsDatabase.sqlite3"];
createdDatabaseOk = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
}
Just call in your AppDelegate - not too messy really?
Easy. Look first to see if it's in the documents directory. If it's not, find it inside your app's Resources folder ([[NSBundle mainBundle] pathForResource...]), then copy it into the documents directory using [[NSFileManager defaultManager] copyItemAtPath:...]. Then use the fresh copy in the documents directory with impunity.
The final product
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"Cache.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *giveCachePath = [documentsDirectory stringByAppendingPathComponent:#"Cache.plist"];
BOOL fileExists = [fileManager fileExistsAtPath:giveCachePath];
if (fileExists) {
NSLog(#"file Exists");
}
else {
NSLog(#"Copying the file over");
fileExists = [fileManager copyItemAtPath:finalPath toPath:giveCachePath error:&error];
}
NSLog(#"Confirming Copy:");
BOOL filecopied = [fileManager fileExistsAtPath:giveCachePath];
if (filecopied) {
NSLog(#"Give Cache Plist File ready.");
}
else {
NSLog(#"Cache plist not working.");
}