2013-05-27 9 views
8

Sto usando FMDatabaseQueue nella mia applicazione iOS. Sono bloccato nel capire come restituire il valore sulla creazione della coda. Apprezzo il tuo aiuto !!FMDatabaseQueue Come restituire un valore

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath]; 

[queue inDatabase:^(FMDatabase *db) { 
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; 
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; 
[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; 

FMResultSet *rs = [db executeQuery:@"select * from foo"]; 
while ([rs next]) { 
    ... 
} 
// I want value to be returned from here 
}]; 
+0

cosa vuoi tornato? Un singolo valore, o un insieme (o una matrice) di risultati dal db (che è quello che sembra si stia provando a fare tramite "' select * '" lassù) ??? –

risposta

0

si può passare un altro le cose nel metodo di blocco, come nell'esempio qui sotto

se si legge la pagina di FMDB's Github Page si potrebbe capire come funzionano le cose

[queue inTransaction:^(FMDatabase *db, BOOL *rollback) { 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; 

    if (whoopsSomethingWrongHappened) { 
     *rollback = YES; 
     return; 
    } 
    // etc… 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]]; 
}]; 






FMDatabaseQueue will run the blocks on a serialized queue 
(hence the name of the class). So if you call FMDatabaseQueue's 
methods from multiple threads at the same time, they 
will be executed in the order they are received. 
This way queries and updates won't step on each other's toes, 
and every one is happy. 

    Note: The calls to FMDatabaseQueue's methods are blocking. So even though you are passing along blocks, they will not be run on another thread. 
+0

So che sto facendo una piccola domanda strana, ma da dove ottieni questo "whoops Something SomethingHappened". Lo hai già dichiarato da qualche parte? l'aiuto sarà molto apprezzato – Nik

+0

@Nik è su FMDB github page https://github.com/ccgus/fmdb –

15

Dipende da cosa si sta cercando ritornare. Ma quello che potrebbe confondere te è che se emetti un'istruzione return all'interno del blocco inDatabase, stai tornando dal blocco, non stai tornando dal metodo che contiene questo blocco inDatabase.

Pertanto, non si restituiscono valori dal blocco inDatabase, ma si restituiscono valori dall'esterno del blocco. Quindi, cosa farai comunemente, dichiarerai la tua variabile da restituire al di fuori del il blocco inDatabase, il tuo blocco inDatabase lo aggiornerà, e poi, quando il blocco sarà terminato, sarà restituito il risultato (non da all'interno del blocco inDatabase).

Un esempio comune è se si sta costruendo un NSMutableArray: Quindi creare l'array mutabile al di fuori del blocco, e quindi aggiungere i valori all'interno del blocco, ma poi restituisce i risultati dopo si esce dal blocco inDatabase:

NSMutableArray *results = [NSMutableArray array]; // declare this outside the block 

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath]; 

[queue inDatabase:^(FMDatabase *db) { 

    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @(1)]; 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @(2)]; 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @(3)]; 

    FMResultSet *rs = [db executeQuery:@"select * from foo"]; 
    while ([rs next]) { 
     ... 
     [results addObject:result];     // add values inside the block 
    } 
    [rs close]; 
}]; 

return results;          // return the results outside the block 

oppure, se hai a che fare con un certo tipo fondamentale, come un NSInteger o BOOL o quello che hai, che ci si dichiara la variabile con un qualificatore __block. Ad esempio, io uso questo per restituire un successo variabile BOOL, ad es .:

__block BOOL success;        // again, define outside the block 

NSMutableArray *results = [NSMutableArray array]; 
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath]; 

[queue inDatabase:^(FMDatabase *db) { 

    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @(1)]; 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @(2)]; 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", @(3)]; 

    FMResultSet *rs = [db executeQuery:@"select * from foo"]; 
    if (!rs) 
    { 
     NSLog(@"%s: %@", __FUNCTION__, [db lastErrorMessage]); 
     success = NO;  // set the value inside the block 
     return;   // note, this doesn't exit the method; this exits this `inDatabase` block 
    } 

    while ([rs next]) { 
     ... 
    } 

    [rs close]; 
    success = YES;  // another example of setting that `success` variable 
}]; 

// so whether I successfully completed the block, or whether I hit the `return` 
// statement inside the block, I'll fall back here, at which point I'll return my 
// boolean `success` variable 

return success;   // don't return the value until after you exit the block 

Anche se questo potrebbe sembrare confondere la prima volta che lo si incontra, è utile per capire questo. Quando inizi a utilizzare molto il blocco GCD, questo schema è molto comune. Quando si dispone di un blocco (indicato dal carattere ^), è quasi necessario pensarlo come una funzione che si sta definendo all'interno del metodo principale. Quando si incontra uno return all'interno di un blocco, si ritorna al metodo che contiene il blocco.

Per introduzioni ai blocchi vedere:

+0

Nel mio caso per restituire un Bool in swift, ritorna prima, quindi la funzione all'interno del blocco (chiusura) viene eseguita successivamente. Quindi restituisce sempre false. Qualche idea? –

+1

Con FMDB? Il metodo 'inDatabase' viene eseguito in modo sincrono. L'unica volta che hai il problema che descrivi è quando stai facendo qualcosa in modo asincrono. Se stessimo facendo qualcosa in modo asincrono, non avresti (a) tentato di restituire il valore immediatamente; ma piuttosto (b) implementa il tuo modello di completamento del completamento (ad esempio, come mostrato in [questa domanda di rete asincrona] (http://stackoverflow.com/a/26569930/1271826)). Ma non devi occupartene se non spedisci qualcosa in modo asincrono. – Rob

+0

Ben spiegato, grazie mille! – Rexb

Problemi correlati