2013-05-27 20 views
8

Ich verwende FMDatabaseQueue in meiner iOS-Anwendung. Ich bin im Verstehen, wie man den Wert beim Erstellen der Warteschlange zurückgibt. Schätze deine Hilfe!!FMDatabaseQueue So geben Sie einen Wert zurück

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

was wollen Sie zurück? Ein einzelner Wert, oder ein Satz (oder Array) von Ergebnissen aus der db (was ist, wie es aussieht, versuchen Sie über "' wählen * '" da oben) ??? –

Antwort

0

Sie können unter

weitere Dinge in Block Verfahren wie das Beispiel passieren, wenn Sie die FMDB's Github Page Seite lesen können Sie verstehen, wie die Dinge funktionieren

[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

Ich weiß, ich stelle eine etwas seltsame Frage, aber woher bekommst du das "whoopsSomethingWrongHappened". Hast du es früher irgendwo erklärt? Hilfe wird wirklich geschätzt. – Nik

+0

@Nik es ist auf FMDB github Seite https://github.com/ccgus/fmdb –

15

Es hängt davon ab, was Sie versuchen, zurückgeben. Was Sie jedoch verwirren könnte, ist Folgendes: Wenn Sie innerhalb des Blocks inDatabase eine return-Anweisung ausgeben, kehren Sie aus dem Block zurück, und Sie kehren nicht von der Methode zurück, die diesen Block inDatabase enthält.

Sie geben also einfach keine Werte aus dem inDatabase Block zurück, sondern geben Werte von außerhalb des Blocks zurück. Was Sie normalerweise tun, ist, dass Sie Ihre Variable als außerhalb Block inDatabase deklarieren, Ihr inDatabase Block wird es aktualisieren, und dann, wenn der Block fertig ist, das ist, wenn Sie die Ergebnisse (nicht aus innerhalb des inDatabase Blocks).

Ein gängiges Beispiel ist, wenn Sie ein NSMutableArray Gebäude sind: So außerhalb des Blocks der änderbaren Array erstellen, und dann Werte hinzufügen, aus dem Block, aber dann wieder die Ergebnisse nach verlassen Sie den inDatabase Block:

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 

oder, wenn Sie mit einigen grundlegenden Art zu tun haben, ein wie NSInteger oder BOOL oder, was Sie haben, dann würden Sie die Variable mit einem __block Qualifier erklären. Zum Beispiel werde ich diese verwenden, um einen BOOL Erfolg Variable zurückzukehren, z.B .:

__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 

Während dies erscheinen mag das erste Mal verwirrend Sie es begegnen, ist es sinnvoll, dies zu verstehen. Wenn Sie GCD viel blockieren, ist dieses Muster sehr verbreitet. Wenn Sie einen Block haben (durch das Zeichen ^ angezeigt), müssen Sie fast als eine Funktion, die Sie in Ihre Hauptmethode definieren. Wenn Sie in einem Block auf eine return stoßen, kehren Sie zu der Methode zurück, die den Block enthält.

Für Einführungen in Blöcke zu sehen:

+0

In meinem Fall, um ein Bool in Swift zurückzugeben, es zuerst zurück, dann die Funktion innerhalb Block (Schließung) später ausführen. Es wird also immer falsch zurückgegeben. Irgendeine Idee? –

+1

Mit FMDB? Die 'inDatabase'-Methode wird synchron ausgeführt. Das einzige Problem, das Sie beschreiben, ist, wenn Sie etwas asynchron machen. Wenn Sie etwas asynchron tun, würden Sie (a) nicht versuchen, den Wert sofort zurückzugeben; (b) Implementieren Sie stattdessen Ihr eigenes Beendigungshandlermuster (z. B. wie in [diese asynchrone Netzwerkfrage] (http://stackoverflow.com/a/26569930/1271826) gezeigt). Aber Sie müssen sich damit nicht befassen, es sei denn, Sie senden etwas asynchron. – Rob

+0

Schön erklärt, danke eine Tonne! – Rexb

Verwandte Themen