I've implemented a singelton with an FMDatabase using the following code, which seems to have resolved the issue with the locked Database error. Not sure if this is good practice, but here's the code for everyone that needs a similar implementation. I used this tutorial on singeletons.
The singleton:
DatabaseController.h:
#import <Foundation/Foundation.h>
#import "FMDatabase.h"
@interface DatabaseController : NSObject
@property (strong, nonatomic) FMDatabase *db;
+ (id)sharedDatabase;
- (void)initDB;
- (FMDatabase *)getDB;
@end
DatabaseController.m:
#import "DatabaseController.h"
@implementation DatabaseController
static DatabaseController *sharedDatabase = nil;
// Get the shared instance and create it if necessary.
+ (DatabaseController *)sharedDatabase {
if (sharedDatabase == nil) {
sharedDatabase = [[super allocWithZone:NULL] init];
}
return sharedDatabase;
}
- (void)initDB {
NSString *databaseName = @"MyDatabase.db";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDir = [documentPaths objectAtIndex:0];
NSString *databasePath = [documentDir stringByAppendingPathComponent:databaseName];
_db = [FMDatabase databaseWithPath:databasePath];
if (![_db open])
NSLog(@"Database problem");
}
// Return database instance
- (FMDatabase *)getDB {
return _db;
}
// We can still have a regular init method, that will get called the first time the Singleton is used.
- (id)init {
self = [super init];
if (self) {
// Work your initialising magic here as you normally would
}
return self;
}
// Equally, we don't want to generate multiple copies of the singleton.
- (id)copyWithZone:(NSZone *)zone {
return self;
}
@end
Using the singelton
Then everywhere I need to acces the database I use:
DatabaseController* sharedDatabase = [DatabaseController sharedDatabase];
[sharedDatabase initDB]; //only the first time! In my case in my app delegate
FMDatabase *db = [sharedDatabase getDB];