I am using SQLite via FMDB in my app, and it's been working for the past couple months on all the XCode simulators, however, when I am now testing on an actual device, I seem to be getting problems when I try to insert.
The error I'm getting is:
error domain = fmdatabase code=14 "unable to open database file" UserInfo = 0x178665340 {NSLocalizedDescription=unable to open database file}
Here's my code:
I have all of my FMDB stuff wrapped in a Helper Class I created:
_lHelper = [[BTRLocationsDatabaseHelper alloc] init];
self.dbString = [_lHelper checkTableAndCreate:TABLE_LOCAL_LOCATIONS];
That calls:
NSString *const LOCATIONS_DB_PATH = @"/Library/Caches/myapp_locations.db";
NSString *const TABLE_LOCAL_LOCATIONS = @"locallocations";
NSString *const TABLE_FAVORITE_LOCATIONS = @"favoritelocations";
- (instancetype)init {
self = [super init];
if(self) {
_db = [FMDatabase databaseWithPath:LOCATIONS_DB_PATH];
if(![_db open]) {
NSLog(@"Error opening myapp_locations database");
}
}
return self;
}
-(NSString *)checkTableAndCreate:(NSString *)table {
NSString *errorString = @"";
FMResultSet *rs = [self.db executeQuery:@"select DISTINCT tbl_name from sqlite_master where tbl_name = ?", table];
[rs next];
BOOL errors = NO;
if([rs hasAnotherRow]) {
// table exists - I think -> So here we would do nothing
NSLog(@"locallocations table existed");
} else {
NSLog(@"locallocations table does not exist");
// table does not exist - I think -> So here we would create the table
if([table isEqualToString:TABLE_LOCAL_LOCATIONS]) {
NSLog(@"Creating a new locallocations table");
BOOL success = [self.db executeUpdate:@"create table locallocations .....)"];
if(!success) {
errors = YES;
NSString *err = [NSString stringWithFormat:@"%@", [self.db lastError]];
[errorString stringByAppendingString:err];
NSLog(@"Error create table locallocations: %@", [self.db lastError]);
}
}
}
FMResultSet *rsFavorites = [self.db executeQuery:@"select DISTINCT tbl_name from sqlite_master where tbl_name = ?", @"favoritelocations"];
[rsFavorites next];
BOOL errorsFavorites = NO;
if([rsFavorites hasAnotherRow]) {
// table exists - I think -> So here we would do nothing
NSLog(@"favoritelocations table existed");
} else {
NSLog(@"favoritelocations table does not exist");
NSLog(@"Creating a new favoritelocations table");
// table does not exist - I think -> So here we would create the table
BOOL success = [self.db executeUpdate:@"create table favoritelocations ...."];
if(!success) {
errorsFavorites = YES;
NSString *err = [NSString stringWithFormat:@", %@", [self.db lastError]];
[errorString stringByAppendingString:err];
NSLog(@"Error create table favoritelocations: %@", [self.db lastError]);
}
}
// Down here we would do logic for adding new columns if we ever need them - if errors is false
return errorString;
}
After that's done I print out errorString and it's empty so that makes me believe the table creation worked.
Then I later try to do an insert calling this method in the Helper Class:
-(NSString *)insertFavoriteLocation:(BTRLocation *)location
userId:(int)userId {
NSMutableDictionary *dictionaryArgs = [NSMutableDictionary dictionary];
//... just adding stuff to my dictionary
BOOL result = [self.db executeUpdate:@"insert into favoritelocations ....];
NSError *error = [self.db lastError];
NSString *errorString = [NSString stringWithFormat:@"%@", error];
return errorString;
}
After that runs I print out errorString and it says the error I pasted above, error code 14 unable to open database file.
So this works perfectly on a Simulator, what could be causing this to not work on a device (iPhone 5s to be specific, but that's the only device I've tried).
Thanks!
EDIT:
NSString* path = [NSSearchPathForDirectoriesInDomains(
NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
Solution:
For those that care, this is how I ended up fixing it:
Modified the init method to have:
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(
NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *dbPath = [cachePath stringByAppendingPathComponent:@"myapp_locations.db"];
_db = [FMDatabase databaseWithPath:dbPath];