2009-11-03 9 views
0

J'ai réussi à accéder à ma base de données pour obtenir une liste de villes lors du lancement de l'application. J'ai essayé d'exécuter une seconde requête par la suite pour obtenir la liste des états mais tout ce qui se passe est que mon application explose sans erreur utilisable dans la console (dit simplement "Program received signal: EXEC_BAD_ACCESS" et rien de plus).Accès à une base de données SQLite pour deux requêtes distinctes sur l'iPhone App Initialisation

Voici le code, j'espérais que quelqu'un pourrait me expliquer ce que je fais mal:

-(void) initializeDatabase{ 
// The database is stored in the application bundle 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"mydatabase.sqlite"]; 

// Open the database. The database was prepared outside the application. 
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK){ 
    [self initializeCities:database]; 
    [self initializeStates:database]; 
} else { 
    // Even though the open failed, call close to properly clean up resources. 
    sqlite3_close(database); 
    NSAssert1(0, @"Failed to open database with message '%s'.", sqlite3_errmsg(database)); 
    // Additional error handling, as appropriate... 
} 
    } 

-(void) initializeCities:(sqlite3 *)db { 
NSMutableArray *cityArray = [[NSMutableArray alloc] init]; 
self.cities = cityArray; 
[cityArray release]; 

// Get the primary key for all cities. 
const char *sql = "SELECT id FROM my_table ORDER BY state"; 
sqlite3_stmt *statement; 

if (sqlite3_prepare_v2(db, sql, -1, &statement, NULL) == SQLITE_OK){ 
    while (sqlite3_step(statement) == SQLITE_ROW){ 
     int primaryKey = sqlite3_column_int(statement, 0); 
     City *city = [[City alloc] initWithPrimaryKey:primaryKey database:db]; 
     [cities addObject:city]; 
     [city release]; 
    } 
} 

// "Finalize" the statement - releases the resources associated with the statement. 
sqlite3_finalize(statement); 
} 

-(void) initializeStates:(sqlite3 *)db { 
NSMutableArray *statesArray = [[NSMutableArray alloc] init]; 
self.states = statesArray; 
[statesArray release]; 

// Get the primary key for all cities. 
const char *sql = "SELECT DISTINCT state FROM my_table ORDER BY state"; 
sqlite3_stmt *statement; 

if (sqlite3_prepare_v2(db, sql, -1, &statement, NULL) == SQLITE_OK){ 
    // We "step" through the results - once for each row 
    while (sqlite3_step(statement) == SQLITE_ROW){ 
     NSString *state; 
     state = (NSString *)sqlite3_column_text(statement, 0); 

     [states addObject:state]; 
     [state release]; 
    } 
} 

// "Finalize" the statement - releases the resources associated with the statement. 
sqlite3_finalize(statement); 
} 

Je ne peux pas déboguer ce code comme le débogueur frappe jamais mes points d'arrêt du tout. Si je supprime la méthode initializeStates, l'application fonctionne comme prévu (albiet sans liste d'états).

+1

Si vous utilisez un emballage, ce sera plus facile à déboguer (et pourrait même faire disparaître votre problème). http://cocoaheads.byu.edu/resources/sqlite –

+0

Un "wrapper" étant quoi exactement? Je suis un programmeur .Net par le commerce. Un wrapper serait-il l'équivalent d'un bloc Try ... Catch? –

Répondre

1

Vous publiez « état » sans avoir alloué elle. Essayez quelque chose comme ceci:

while (sqlite3_step(statement) == SQLITE_ROW){ 
    NSString *state = [[NSString alloc] initWithCString:(char*)sqlite3_column_text(statement, 0) encoding:NSASCIIStringEncoding]; 
    //state = (NSString *)sqlite3_column_text(statement, 0); 

    [states addObject:state]; 
    [state release]; 
} 

Mise à jour: add jeter ci-dessus pour fixer le compilateur d'avertissement

+0

Votre méthode a fonctionné, mais elle me donne un avertissement de: "avertissement: cibles de pointeur en passant l'argument 1 de 'initWithCString: encodage:' diffèrent en signés" Une idée de ce que cela signifie? –

+2

@Pselus cela signifie que 'initWithCString: encoding:' veut un 'const char *', mais 'sqlite3_column_text()' renvoie un 'const unsigned char *'. C'est un avertissement assez sûr à ignorer, et vous pouvez le faire partir avec une distribution. –

1

Votre problème est le suivant:

NSString *state = (NSString *)sqlite3_column_text(statement, 0); 

Selon the documentation, sqlite3_column_text() retourne un char*, pas NSString*.

Edit: Vous ne l'auriez pas eu ce problème si vous avez utilisé un emballage;)