Ошибка (“EXC_BAD_ACCESS”) при попытке открыть (создать) SQLite d / b

#objective-c #sqlite

#objective-c #sqlite

Вопрос:

Вот код … кто-нибудь видит, что не так? Кроме того, почему второй NSLog «errmsg» вызывает сбой отладчика при отладке на устройстве (iPhone 3GS)

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

    NSString *sqlCommand = @"CREATE TABLE CardData (card_id TEXT PRIMARY KEY NOT NULL, card_name TEXT NOT NULL, "
        @"card_type TEXT, cide_val TEXT, create_date TEXT DEFAULT CURRENT_DATE, user_notes TEXT, gps_loc TEXT)"; 
    const char cSQLCommand = [sqlCommand cStringUsingEncoding:NSUTF8StringEncoding];
    char * errmsg = NULL;   

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

    BOOL fileExists = [fileManager fileExistsAtPath:databasePath];
    if(!fileExists)  {
        if(sqlite3_open(cDatabasePath, db) == SQLITE_OK) { // doesn't exist, so create it...
            sqlite3_exec(db, amp;cSQLCommand, NULL, NULL, amp;errmsg);  //  now create the table...
            NSLog(@"error: %@", errmsg);
        }
  

Комментарии:

1. Только мазохисты используют SQLite C API непосредственно в Objective-C. Вместо этого используйте FMDB (оболочку SQLite) или CoreData (диспетчер графов объектов).

2. Я уважаю ваше мнение… однако я решил использовать API напрямую, в основном для обучения… можете ли вы сказать мне, почему я получаю ошибку sqlite3_open?

Ответ №1:

Происходит сбой, потому что errmsg это не объект Objective-C, который вам требуется при использовании %@ замены. errmsg является char * , что означает, что вы должны использовать %s .

Что касается причины сбоя….

sqlite3_open определяется как:

 int sqlite3_open(
  const char *filename,   /* Database filename (UTF-8) */
  sqlite3 **ppDb          /* OUT: SQLite db handle */
);
  

Ваш db объявлен как sqlite3* . Другими словами, вы передаете неправильную вещь. Вы должны делать:

 sqlite3_open(cDatabasePath, amp;db)
  

Хотя ваше желание разобраться в SQLite C API велико, я все еще думаю, что вам следует использовать FMDB. Это действительно устраняет ошибки такого рода и позволяет вам сосредоточиться на реальных проблемах с вашим кодом.

Комментарии:

1. Я ненавижу Objective-C! Это не имеет никакого смысла для .NET-программистов вроде меня! Я пытаюсь изучить это, но, как вы можете видеть, для меня это настоящая борьба … спасибо за помощь, я действительно ценю это. У меня будет еще один запрос о помощи через несколько минут: D