I am new to sQLite and created a sqlite database in the mac's terminal for my app. I then added the database too my app and ran fine. Recently I needed another table, so i downloaded sqlitemanager(a firefox plugin with a gui for sqlite databases, kinda didnt want to write script for everysingle thing). From since then, I have been getting the error "Table not found". However browsing my database i see the table, but if i look at the database in the ios simulator i dont see the tables(database is zero kb so i guess the error is justified). However, if I just copy and paste the database directly into that folder the app works fine. However this is not a good fix...but is this occuring because i used
this manager to edit the database? If yes what manager can i use or if no what is the problem.
Thank you
+ (NSString *) getDBPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:#"tourism.sql"];
}
+ (void) copyDatabaseIfNeeded {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dbPath = [DBAccess getDBPath];
BOOL success = [fileManager fileExistsAtPath:dbPath];
if(!success) {
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"tourism.sql"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
Related
when i use simulator,i can find the database file in /documents .but when i use my iPhone to run the project,i can not find the database file.
what time should i create the database file or use this code in my project?
NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentFolderPath = [searchPaths objectAtIndex:0];
NSString *dbFilePath = [documentFolderPath stringByAppendingString:DATABASENAME];
NSFileManager *fm = [NSFileManager defaultManager];
BOOL isExist = [fm fileExistsAtPath:dbFilePath];
if (!isExist) {
NSString *backupDbPath = [[[NSBundle mainBundle]resourcePath]stringByAppendingString:DATABASENAME];
[fm copyItemAtPath:backupDbPath toPath:dbFilePath error:nil];
}
For the first time or the database file does not exist in the documents directory, you have to copy DB file to document directory:
-(void)copyDatabaseIntoDocumentsDirectory{
// Check if the database file exists in the documents directory.
NSString *destinationPath = [self.documentsDirectory stringByAppendingPathComponent:self.databaseFilename];
if (![[NSFileManager defaultManager] fileExistsAtPath:destinationPath]) {
// The database file does not exist in the documents directory, so copy it from the main bundle now.
NSString *sourcePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:self.databaseFilename];
NSError *error;
[[NSFileManager defaultManager] copyItemAtPath:sourcePath toPath:destinationPath error:&error];
// Check if any error occurred during copying and display it.
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
}
}
Ref: http://www.appcoda.com/sqlite-database-ios-app-tutorial/
You can't access the directories of iPhone or iPad. So even if you successfully created a database, you won't see it. You can judge its existence by read data from it.
I have the following code snippet that creates a writable version of my .sqlite file on my test phone:
NSFileManager *fileMgr = [NSFileManager defaultManager];
// First, test for existence of writable file:
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"pictures.sqlite"];
BOOL success = [fileMgr fileExistsAtPath:writableDBPath];
if (!success){
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"pictures.sqlite"];
success = [fileMgr copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
The copy of pictures.sqlite that I have on my Mac has 3 tables, and is the most recent version of the database. The .sqlite file on my phone only has 2 tables, which reflects an older version of the DB. I cannot figure out how to update the phone to hold the new database. Can somebody help me do this?
When you app is started, check the version of the database. (In this case, check if the third table exists.)
If it is too old, update it. (That is, copy the new version from the resources, or manually create the third table.)
My problem is it always import sqlite database (it has so many setup data already) from resources file whenever render my app. First time I render my apps, it import sqlite database from resource file and I insert some data into the table. But second time render again, it import again and lost my inserted records. Following is my coding.
What I want to it does not need to import if database exist.
static NaWinDatabase *_database;
+ (NaWinDatabase*)database {
if (_database == nil) {
_database = [[NaWinDatabase alloc] init];
}
return _database;
}
- (id)init {
if ((self = [super init])) {
NSString *sqLiteDb = [[NSBundle mainBundle] pathForResource:#"nawin" ofType:#"sqlite3"];
if (sqlite3_open([sqLiteDb UTF8String], &_database) != SQLITE_OK) {
NSLog(#"Failed to open database!");
}
}
return self;
}
copyDatabaseIfNeeded will copy your resource database to the application directory folder if it is not copied for the first time
+ (void) copyDatabaseIfNeeded {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dbPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:dbPath];
if(!success) {
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"db.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable database file with message \"%#\".", [error localizedDescription]);
}
}
//Path that saves your database in application document directory
+ (NSString *) getDBPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:#"db.sqlite"];
}
Just check if the SQLite DB exists at app launch and if it does not then import it, if it does exist do not import. The SQLite DB is just a file.
sqlite3's sqlite3_open succeeds whether or not the file exists.
I assume your database is created from SQL. If so and you want to see if the database has been set up yet, you can do a pragma schema_version; query against the database connection. If it returns 0, there are no tables yet. Any other value, and you've created the tables.
Make sure your table creation and record insertion are atomic and you should have no further troubles.
I haven't used sqlite on iOS recently but I recall having to open the database in the document directory. I believe for security reasons the main bundle can not be modified. Essentially your database is read only.
I do something like:
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *dbPath = [docsPath stringByAppendingPathComponent:name];
fmdb = [FMDatabase databaseWithPath:dbPath];
[fmdb open];
try this may be help full... It's working fine
- (void)copyDatabaseIfNeeded {
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"carDatabase.sqlite"];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success)
return;
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"carDatabase.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
NSLog(#"Result For Database path %c",success);
if (!success) {
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
NSLog(#"Result For Database path %c",success);
}
//Get DataBase Path
- (NSString *) getDBPath {
NSString *sqLiteDb = writableDBPath ; // [[NSBundle mainBundle] pathForResource:#"liveonmap_iphone" ofType:#"sqlite"];
return sqLiteDb;
}
Cheers...
I am working with the sqlite database and everything is going well. I added 4 entries in the table, and then added textview on my xib file. Now i want that this data should be fetched from the sqlite database which is placed in the bundle of the project. But i am not getting how to call this database from the bundle to thedirectory path. Please help me out regarding this issue.
Use this code:
First call this method which will check wheter dbfile is stored in documents Directory or not. If not It will write your file to documents directory.
-(void)openDatabase {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
NSString *dbPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:dbPath];
if(!success) {
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:#"databasefilename.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath
error:&error];
if (!success)
NSLog(#"Failed to create writable database file with message '%#'.",
[error localizedDescription]);
}
}
- (NSString *) getDBPath {
//Search for standard documents using NSSearchPathForDirectoriesInDomains
//First Param = Searching the documents directory
//Second Param = Searching the Users directory and not the System
//Expand any tildes and identify home directories.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory ,
NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:#"databasefilename.sqlite"];
}
Then check in Appdelegate or any other class where you want:
if (sqlite3_open([[self getDBPath] UTF8String], &YOUR_SQLITE3_OBJECT) == SQLITE_OK) {
NSLog(#"database opened successfully");
}
I get these warnings, every time my app opens from a new state... but I think this is from when the app opens for the first time, it copies the sqlite database.
WARNING: Slow defaults initialization - setup took 0.027397 seconds
WARNING: Slow defaults access for key Internal took 0.094897 seconds, tolerance is 0.020000
Below is the copy code:
- (void) copyDatabaseIfNeeded {
//Using NSFileManager we can perform many file system operations.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dbPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:dbPath];
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"db.sqlite"];
if (success) {
success = [fileManager contentsEqualAtPath:defaultDBPath andPath:dbPath];
if (!success) {
BOOL isE = [fileManager removeItemAtPath:dbPath error:&error];
if (!isE)
NSAssert1(0, #"Failed to remove corrupt database file with message '%#'.", [error localizedDescription]);
}
}
if(!success) {
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
- (NSString *) getDBPath
{
//Search for standard documents using NSSearchPathForDirectoriesInDomains
//First Param = Searching the documents directory
//Second Param = Searching the Users directory and not the System
//Expand any tildes and identify home directories.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
//NSLog(#"dbpath : %#",documentsDir);
return [documentsDir stringByAppendingPathComponent:#"db.sqlite"];
}
How do I prevent my app from giving me these warnings? Is this the normal method when copying a database for SQLite? I know that the database is only being copied once in a while, but i really don't like seeing warnings in the log.