I create database and put *.sqlite file in recources folder in Xcode. Before opening database I copy it to documents folder from resources.
This works fine on simulator, but does not work on iPhone.
For some reasons database file does not exists in iPhone device. This is my code:
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *databasePath = [documentsDir stringByAppendingPathComponent:databaseFileName];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL success = [fileManager fileExistsAtPath:databasePath];
if(!success) // all the time it's YES, even if I delete database
{
// copy database from application folder
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseFileName];
BOOL fileExists = [fileManager fileExistsAtPath:databasePathFromApp];
if (fileExists) { // It's NO, for some reasons database does not exist
[fileManager removeItemAtPath:databasePath error:nil];
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
}
[fileManager release];
}
return databasePath;
For some reasons this line returns NO all the time
BOOL fileExists = [fileManager fileExistsAtPath:databasePathFromApp];
the path in databasePathFromApp somthing like this
/var/alexander/xxx-xxx-xxx-xxx..../AppName.app/database.sqlite
The question is: why database does not exists in recources?
Finaly found the problem. iPhone device care about file name register, so "database.sqlite" and "DataBase.sqlite" is different files for device, but the same files for simulator. It's so weird.
I posed it in the blog
Can't open file in iPhone device, but can in iPhone simulator
Delete database from resource & add it once again &
check box appears at top with Copy items into destination group folder.
Clean targets & reset simulator.
Related
I have searched everywhere but could not find answer to this question. I have made an app that uses previous build Sqlite database. On Simulator My database file is at
/Users/idsMac/Library/Application Support/iPhone Simulator/7.1/Applications/AAAAAAAA-CCCCC-DDDD-7777-PPPPPPPPPP/Documents/
I am using the following code to read this Sqlite Database file.
-(NSString *)dataFilePath{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths lastObject];
return [documentsDirectory stringByAppendingPathComponent:#"punDictionary.sqlite"];
}
if((sqlite3_open([[self dataFilePath] UTF8String], &_database)) != SQLITE_OK){
NSLog(#"Failed to open Database");
}else{
NSLog(#"Database Connceted ..... ");
}
My App is working great on Simulator .. But When I test it on my IOS Device. It is not detecting the Database.
My question is how shall I add the sqlite Database file to my app to test on Device ?
Thanks in Advance !
Include the Sqlite DB file into your project, and copy it into Documents folder if not exist when the app access the DB file.
#define DB_NAME #"XXX.sqlite"
#define DB_FULLPATH [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:DB_NAME]
+ (void)createDatabase
{
NSFileManager *fileManager = [NSFileManager defaultManager];
if(![fileManager fileExistsAtPath:DB_FULLPATH]) {
NSString *bundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:DB_NAME];
[fileManager copyItemAtPath:bundlePath toPath:DB_FULLPATH error:nil];
}
}
Hoping someone can help a new iOS developer out - I have a ready made sqlite database called teamresults.db that I added to the project using "Add Files..." but when I'm using the below code I seem to be connecting/referencing an empty database instead of the one that's added (on inspection through the terminal the database the simulator uses is 0mb in size where as the one I've added is around 3mb).
It seems like the application is creating an empty database but I can't work out why? Any thoughts?
For reference I don't get any error messages:
BOOL success;
dbName = #"teamresults.db";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
dbPath = [documentsDir stringByAppendingPathComponent:dbName];
NSFileManager *fileManager = [NSFileManager defaultManager];
success = [fileManager fileExistsAtPath:dbPath];
if(success) {
return;
}
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:dbName];
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePathFromApp error:nil];
There seems to be something wrong with this line of code:
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePathFromApp error:nil];
The correct one would be:
[fileManager copyItemAtPath:databasePathFromApp toPath:dbPath error:nil];
You should copy database to sandbox path instead of resources path !!
Do one thing. Delete the database added by right click on that and click delete instead of "Delete reference only". Then add it again and don't forget to click on "Copy into destination item". Hopefully that would help you.
I have an app leveraging Core Data SQLITE3 that works perfectly in the simulator. However i do not understand how to update the DB on the device, which i guess is the same as in app-store.
I update the DB from .txt files in the app and create the DB, this function is there only for creating the DB and will be removed in the final version. My idea is to create the DB in the simulator, lock the update part of the code and then distribute the package with an updated database.
However, when i rebuild my app on the device it still have the old data in the DB.
I have been looking around but i am afraid i do not fully understand how to solve this. I did find this thread: Can't refresh iphone sqlite3 database
I would very much appreciate if some nice person could share some light on this and help me to solve this.
Cheers
Have you copied the db file from the bundle directory (which is read only) to a writable one? (like the documents directory of each application?).
When trying to save in the device did you get a sqlite error like this?
SQLITE_READONLY 8 /* Attempt to write a readonly database */
EDIT:
All the files in the main bundle are read only, so if you need to modify one/some of them, you need to copy the files in a location that is writable. Assuming you have called the db mydb.sqlite here is some code that copies the db (only if it does not exists) to the documents directory.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDirectory = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSFileManager *fm = [NSFileManager defaultManager];
NSString *docPath = [docDirectory stringByAppendingPathComponent:#"mydb.sqlite"];
if (![fm fileExistsAtPath:docPath]) { // file does not exists, copy it
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:#"mydb" ofType:#"sqlite"];
NSError *error = nil;
BOOL res = [fm copyItemAtPath:bundlePath toPath:docPath error:&error];
if (!res) {
// do something with error
}
}
Actually to use .db file inside the Bundle - it's a very bad idea.
Every thime, when I am using .db file, i am checking, if it allready exists inside my Application document directory, and then I will rewrite it.
#define DB_SHOULD_BE_REWRITTEN YES //You should update database and change allready existing db file to file from bundle
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"db.sqlite"];
BOOL success = [fileManager fileExistsAtPath:writableDBPath];
if (!success || DB_SHOULD_BE_REWRITTEN)
{
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"db.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
dbPath = writableDBPath;
I'm working on a new iPhone project and I'm running into problems with sqlite. I've done this before on a different project and it worked just fine so I'm not sure exactly what is going on with this one. I'm using the same code from before, but the situation is a little different.
First of all, I'm trying this time to use Unit Testing so I've created a Cocoa Unit Test Bundle, and I got that working correctly, then I wanted to make a Unit Test for my sqlite database.
The first thing run with this test is [self checkAndCreateDatabase] which is as follows:
-(void) checkAndCreateDatabase{
BOOL success;
// Create a FileManager object, we will use this to check the status
// of the database and to copy it over if required
NSFileManager *fileManager = [NSFileManager defaultManager];
// Check if the database has already been created in the users filesystem
success = [fileManager fileExistsAtPath:databasePath];
// If the database already exists then return without doing anything
if(success) return;
// If not then proceed to copy the database from the application to the users filesystem
// Get the path to the database in the application package
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
// Copy the database from the package to the users filesystem
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
[fileManager release];
}
Then I attempt to open the database with the following line:
int result = sqlite3_open([databasePath UTF8String], &database);
This fails everytime with error code 14 SQLITE_CANTOPEN, and databasePath is "/Users/labuser/Library/Application Support/iPhone Simulator/Documents/projectfusion.db3".
What is odd is that when I go to that directory, Documents/ isn't there, so if I create that, then it doesn't fail, BUT projectfusion.db3 then has a size of 0kb; the tables aren't there. That makes any sqlite3_prepare_v2() fail, because the tables aren't there. If I manually copy the projectfusion.db3 file to that directory before running, then it works just fine.
Is it because I'm doing this inside the unit tests and the scripts don't have permission or something? Or is it possibly because I'm working on a school computer at my university and can't write to that directory? (I tried logging in as admin and it didn't work either).
Try the code given below,
I've set a macro called TEST so I don't have to keep commenting code out.
- (NSString *)createEditableCopyOfDatabaseIfNeeded {
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
#ifdef TEST
documentsDirectory = [[NSFileManager defaultManager] currentDirectoryPath];
#endif
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:DBNAME];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success) { return writableDBPath;} ;
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:DBNAME];
#ifdef TEST
defaultDBPath = [[NSBundle bundleForClass:[self class]] pathForResource:#"YOURDB" ofType:#"sqlite"];
#endif
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
return (defaultDBPath);
}
Try adding the database to your application bundle in xcode and then copy it to the applications Documents directory. You can get that path using
- (NSString *)applicationDocumentsDirectory {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
NSString *myfile = [[NSBundle] mainBundle] pathForResource:#"fileName" ofType:#"plist"];
NSMutableArray *mydata= [[NSMutableArray alloc] initWithContentsOfFile:myfile];
/* code to modify mydata */
[mydata writeToFile:myfile atomically:YES]
In case of simulator 'fileName.plist' is modified but in case of iphone device file remains unchanged. There is no exception seen either.
Is the above code expected to work fine on both iphone and simulator ?
Also in the debugger when I hover over 'mydata' I see different values in case of simulator and device. In case of simulator I see for example, '5 objects' but in case of actual device it shows '{(int)[$VAR count]}'. Could this be related to file not being written ?
You can't write to files in a bundle's resource directory. On top of that you wouldn't want to, because any changes would be overwritten when you update your app. The documents directory persists across versions and (I believe) it is backed up via itunes.
Here is a snippet that checks the documents directory for a plist. if the file doesn't exist it copies a plist out of the resources into the documents directory.
BOOL success;
NSFileManager* fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"score.plist"];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success) return success;
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"score.plist"]];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
return success;