2011-04-25 16 views
7

estoy utilizando la envoltura del FMDatabase SQLite en C Objetivo y tengo el siguiente problema:base de datos SQLite con FMDatabase Envoltura

estoy corriendo un análisis sintáctico XML y el inserto de DB en un subproceso en segundo plano durante algún contenido que el usuario no lo hace tener acceso a, sin embargo, el usuario es capaz de interactuar con una interfaz de usuario y la base de datos de la sección que se encuentran.

The FMDatabase <FMDatabase: 0x17b7b0> is currently in use. 

azar, voy a tener una notificación "FMDatabase ya en uso" y la matriz nunca será poblada por la base de datos. Yo estaba bajo la impresión de que la clase FMDatabase manejaría la consulta una vez que quedó libre, pero tengo una:

while(contents.count < 1){ 
    sleep(1); 
} 

Con la esperanza de que una vez que la base de datos libera, la matriz estará poblado. También he intentado volver a ejecutar la secuencia de comandos de la población de la matriz si la base de datos está ocupada, pero fue en vano.

Lo siento si esta pregunta es confusa, estoy feliz de aclarar.

Respuesta

7

Tuve el mismo problema.

que me pasa a FMDatabaseQueue para cada base de datos de consulta/actualización que tenía que hacer. Funciona a las mil maravillas !

Usar performSelectorOnMainThread es una buena idea, pero cuando se trata de la codificación real, puede ser bastante complicado pasar sus argumentos y obtener los resultados para su uso posterior.

EDIT: Aquí hay un pequeño ejemplo

-(void) updateTaskStateAsync:(NSNumber *)taskID withNewStatus:(NSNumber *)state andCompletionBlock:(void(^)(BOOL status))completionBlock{ 

    NSString *errInfo = [NSString stringWithFormat:@"taskID %d - state %d", [taskID intValue], [state intValue]]; 

    [queue inDatabase:^(FMDatabase *db) { 
     BOOL r = [db executeUpdate:@"UPDATE tasks SET state=?, date_job_last_updated=? WHERE identifier=?", state, [NSDate dateWithTimeIntervalSinceNow:0], taskID]; 
     DB_DISPLAY_ERROR(errInfo); // convenient macro to log errors 

     if(completionBlock) 
      completionBlock(r); 
    }]; 
} 

-(BOOL) updateTaskStateSync:(NSNumber *)taskID withNewStatus:(NSNumber *)state { 

    NSString *errInfo = [NSString stringWithFormat:@"taskID %d - state %d", [taskID intValue], [state intValue]]; 
    __block BOOL r = NO; 
    __block BOOL ended = NO; 

    [queue inDatabase:^(FMDatabase *db) { 
     r = [db executeUpdate:@"UPDATE tasks SET state=?, date_job_last_updated=? WHERE identifier=?", state, [NSDate dateWithTimeIntervalSinceNow:0], taskID]; 
     DB_DISPLAY_ERROR(errInfo); // convenient macro to log errors 

     ended = YES; 
    }]; 

    NSCondition *cond = [[NSCondition alloc] init]; 
    [cond lock]; 
    while(!ended) 
     [cond wait]; 

    [cond unlock]; 

    return r; 
} 
+0

quiero hacer lo mismo que tú, pero para consulta en FMDatabaseQueue, el resultado debe ser de vuelta asíncrono ..... no es muy conveniente. ¿Tienes alguna sugerencia? – flypig

+0

No tengo el problema en realidad. Edité mi respuesta para agregar un código, adjunte su código si no lo ayuda. – dvkch

+0

el código de bloque es ejecutado por FMDB cola de forma asincrónica, y el R será actualizado en el bloque cuando se ejecuta el código de bloque, pero sólo tiene que devolver la r en la última línea de su procedimiento .... Creo que obtendrá vacía resultado de la consulta a veces, dependiendo del estado de la cola fmdb. Esto me confundió por unos días ... puede ser que pasemos un bloque de finalización para devolver el resultado de la consulta, p. "(BOOL) updateTaskState: (NSNumber *) TaskID withNewStatus: (NSNumber *) Estado de fin de: (void (^) (BOOL R)) terminación;" y llamar a la finalización (r) en el [inDatabase cola:^(FMDatabase * db) {..}] bloque. – flypig

4

que está golpeando este problema debido a que su aplicación es multi-hilo y ya está accediendo a la misma FMDatabase de diferentes temas. Una pregunta similar, pero para Python, se puede encontrar here.

FMDatabase es una envoltura alrededor de la API de SQLite. sqlite de forma predeterminada no permite la concurrencia, por lo que FMDatabase usa una variable miembro, llamada "inUse", para rastrear. Para solucionar el problema, pruebe uno de estos métodos definidos en NSObject para que todas las llamadas a FMDatabase se realicen en el mismo hilo.

  • performSelectorOnMainThread: withObject: waitUntilDone:
  • performSelectorOnMainThread: withObject: waitUntilDone: modos:
  • performSelector: onThread: withObject: waitUntilDone:
  • performSelector: onThread: withObject: waitUntilDone: modos:
Cuestiones relacionadas