4

I have been using SQLite for awhile now, and have decided to go to FMDB. I need to make it a singleton. Here's my code below; what do I have to change to have FMDB access the singleton d/b?

#pragma mark Singleton Methods

+ (SQLiteDB *) sharedSQLiteDB  {

    if(!sharedSQLiteDB)  {
        sharedSQLiteDB = [[SQLiteDB alloc] init];
        [sharedSQLiteDB openCreateDB];  //  check to see if d/b exists
    }
    return sharedSQLiteDB;
}   

and this is the code I use to initialize the d/b using FMDB:

//-----------------------    checkIfDatabaseExists    -----------------|
    - (void) openCreateDB  {

        searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  // Get the path to the database file
        documentPath = [searchPaths objectAtIndex:0];
        databasePath = [documentPath stringByAppendingPathComponent:@"ppcipher.s3db"];
        cDatabasePath = [databasePath cStringUsingEncoding:NSUTF8StringEncoding];
        NSLog(@"d/b path: /%@", databasePath);

        NSString *sqlCommand = @"CREATE TABLE CardData (card_id TEXT PRIMARY KEY NOT NULL, card_name TEXT NOT NULL, "
            @"card_type TEXT, code_val TEXT, create_date TEXT DEFAULT CURRENT_DATE, user_notes TEXT, gps_loc TEXT)"; 
        char * errmsg = nil;   

        NSFileManager *fileManager = [NSFileManager defaultManager];
        [fileManager removeItemAtPath:databasePath error:NULL];  //  <------------  delete d/b  TESTING ONLY! 

        BOOL fileExists = [fileManager fileExistsAtPath:databasePath];
        if(!fileExists)  {
            FMDatabase* db = [FMDatabase databaseWithPath: databasePath]; 

            if (![db open]) {
                NSLog(@"Could not open/create database");
            }

            [db executeUpdate:@"CREATE TABLE CardData (card_id TEXT PRIMARY KEY NOT NULL, card_name TEXT NOT NULL, "
             @"card_type TEXT, code_val TEXT, create_date TEXT DEFAULT CURRENT_DATE, user_notes TEXT, gps_loc TEXT)"];

            if(errmsg != nil)
                NSLog(@"error: %s", errmsg);  //  DEBUGGING ONLY!  (REMOVE when done!)
        }
        return;
    }
Joe
  • 56,979
  • 9
  • 128
  • 135
SpokaneDude
  • 4,856
  • 13
  • 64
  • 120
  • A forker of FMDB has a blog post about singletons http://funwithobjc.tumblr.com/post/3478903440/how-i-do-my-singletons and so does Matt Gallagher's Cocoa with Love http://cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html – Joe May 03 '11 at 20:53
  • I know how to do singletons when I start from scratch. Since FMDB is already written, I'm wondering "what" I have to change to make it work. (Do I change my SQLite3 code in first example, or something in the existing FMDB code)? – SpokaneDude May 03 '11 at 20:57
  • It looks to be as simple as only accessing it the database in your application through sharedSQLiteDB. Is that not enough? – Joe May 03 '11 at 21:02
  • That's what I thought also, but then I saw this and didn't know what to do with it... FMDatabase* db = [FMDatabase databaseWithPath: databasePath]; – SpokaneDude May 03 '11 at 21:04
  • I posted an answer, be sure to release the `_database` in dealloc and also look at some of the singleton examples online to make sure your singleton works the way you want (thread safety, memory management) – Joe May 03 '11 at 21:12

1 Answers1

1

Your SQLiteDB class will need to maintain a reference to your FMDatabase so your additional methods will be able to share the same database.

@interface SQLiteDB : NSObject //Or whatever base class
{
    FMDatabase *_database;
}

@end

//implementation

- (void) openCreateDB  {
   ...
   if(!fileExists)  {
      _database = [[FMDatabase databaseWithPath: databasePath] retain];
   ...
   }
}
Joe
  • 56,979
  • 9
  • 128
  • 135
  • Thanks... would you mind explaining to me how _database in the interface causes the one d/b to be used when I open the SQLiteDB? or point me to a doc that would explain it? – SpokaneDude May 03 '11 at 21:19
  • Check out this link http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163-CH12-TPXREF125 It is an instance variable that the class can share. – Joe May 04 '11 at 12:54