8

FMDatabaseQueue在我的 iOS 应用程序中使用。我一直在理解如何在创建队列时返回值。感谢你的帮助!!

 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
}];
4

2 回答 2

15

这取决于您要返回的内容。但是你可能会感到困惑的是,如果你return从块内部发出一个语句inDatabase,你是从块返回的,你不是从包含这个inDatabase块的方法返回的。

因此,您根本不从块中返回值inDatabase,而是从块外部返回值。所以你通常会做的是,你会声明你的变量要在块外返回,inDatabaseinDatabase块会更新它,然后,当块完成时,那就是你返回结果的时候(而不是从inDatabase块内) .

一个常见的例子是,如果你正在构建一个NSMutableArray: 所以在块外创建可变数组,然后从块内添加值,但在退出块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

或者,如果您正在处理一些基本类型,例如 a NSIntegerorBOOL或您有什么,您将使用__block限定符声明变量。例如,我将使用它来返回一个 BOOL 成功变量,例如:

__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

虽然这在您第一次遇到时可能会让人感到困惑,但理解这一点很有用。当你开始大量使用 GCD 块时,这种模式很常见。当您有一个块(由^字符表示)时,您几乎必须将其视为您在 main 方法中定义的函数。当您遇到return块内部时,您将返回到包含该块的方法。

有关块的介绍,请参见:

于 2013-05-27T06:23:32.197 回答
0

您可以在块方法中传递其他内容,如下例所示

如果您阅读FMDB 的 Github 页面页面,您可能会了解事情的运作方式

[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.
于 2013-05-27T04:22:00.100 回答