Creating a plist file only on first runnable in the device's documents directory - iphone

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];
}

Related

Settings.plist iOS

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.

[NSBundle mainBundle]pathForResource returns nil

I'm trying to connect my app to SQLite database but I get messages that tell me that the database is created but there are no tables.
I debugged the program and discovered that
[[NSBundle mainBundle] pathForResource] always returns nil
NSString* file = [[NSBundle mainBundle]pathForResource:_databaseName ofType:_databaseType];
Why is this happening?
Please help me!
First : make sure your database is in the app bundle.
Then you need to implement methods to copy the path to the documentary Directory .as these
-(NSString *) getDBPath:(NSString*)databaseName {
// search for the existed paths
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:databaseName];
}
- (void) InstantiateYourDatabase:(NSString *)DatabaseName {
//Using NSFileManager we can perform many file system operations.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dpname=DatabaseName;
_dbPath = [self getDBPath:dpname];
BOOL success = [fileManager fileExistsAtPath:_dbPath];
NSLog(#"success == %i",success);
if( !success) {
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:DatabaseName];
success = [fileManager copyItemAtPath:defaultDBPath toPath:_dbPath error:&error];
}
}
Tell me if it helps!
try below code for find database path
NSString *databaseName = #"your_db_name.sql";
NSString *databasePath;
// Get the path to the documents directory and append the databaseName
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
NSLog(#"Database Path is: %#",databasePath);
You want More Detail about Sqllite Database Connectivity in iOS try this tutorial
Welcome!
If you created a sqlite db file and drag it to your project in xcode3, it's in application document folder while its running.
NSString *databaseName = #"cartoon.db";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDir = [documentPaths objectAtIndex:0];
NSString *databasePath = [documentDir stringByAppendingPathComponent:databaseName];
Whenever you are using the database you have to use the Documents Directory

Copy folder from Resource to Document in iphone sdk

i have one subfolder in Resources with name SketchImages which contains 300 PNG images, what i need to do is on the startup of my app copy this folder in document folder of iphone sdk, i am trying the following code with no luck
BOOL success;
NSFileManager *fileManager = [[NSFileManager defaultManager] init];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentDBFolderPath = [documentsDirectory
stringByAppendingPathComponent:#"SketchImages"];
success = [fileManager fileExistsAtPath:documentDBFolderPath];
if (success)
{
return;
}else
{
NSString *resourceDBFolderPath = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:#"DB"];
//[fileManager createDirectoryAtPath: documentDBFolderPath attributes:nil];
[fileManager copyItemAtPath:resourceDBFolderPath toPath:documentDBFolderPath
error:&error];
}
any help will be highly appriciated
You use the wrong subfolder name:
NSString *resourceDBFolderPath = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:#"SketchImages"];

iPhone : Unable to copy from MainBundle to NSDocumentDirectory

I am trying to copy a couple of image files from my MainBundle/SampleImages folder to the application NSDocumentDirectory/Library folder, but am unable to do so. I have checked that the images are in .app/Mainbundle/SampleImages directory and I have also checked that the Library folder is being created in the NSDocumentsDirectory, but no files are copied.
I have tried two approaches, given below, but with no success.
here is the code that I am using to copy files.
First Method
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentLibraryFolderPath = [documentsDirectory stringByAppendingPathComponent:#"Library"];
NSString *resourceSampleImagesFolderPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"SampleImages"];
NSData *mainBundleFile = [NSData dataWithContentsOfFile:resourceSampleImagesFolderPath];
[[NSFileManager defaultManager] createFileAtPath:documentLibraryFolderPath
contents:mainBundleFile
attributes:nil];
Second Method
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentSampleImagesFolderPath = [documentsDirectory stringByAppendingPathComponent:#"Library"];
NSString *resourceSampleImagesFolderPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"SampleImages/"];
[fileManager createDirectoryAtPath: documentSampleImagesFolderPath attributes:nil];
if([fileManager copyItemAtPath:resourceSampleImagesFolderPath toPath:documentSampleImagesFolderPath error:&error]) {
NSLog(#"success");
}
else {
NSLog(#"Failure");
NSLog(#"%d",error);
}
I have spent a couple of hours looking for a solution, any help here would be appreciated greatly.
Thank You
Shumais Ul Haq
I got it done with the second method by changing it bit.
There is no need for creating the directory as the SDK docs say that the destination directory must not exist.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentDBFolderPath = [documentsDirectory stringByAppendingPathComponent:#"Library"];
NSString *resourceDBFolderPath = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:#"SampleImages"];
[fileManager copyItemAtPath:resourceDBFolderPath toPath:documentDBFolderPath error:&error];

PList Chicken/Egg Scenario

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.");
}