我一直在尝试,但我只是没有得到很好的阻止。我正在使用FMDatabaseQueue,我正在尝试创建一个非常简单的基于队列的查询。这就是我所拥有的:
-(NSString *) getReferenceForPage:(NSInteger) page
{
[queue inDatabase:^(FMDatabase *db) {
FMResultSet *rs = [db executeQuery:@"SELECT ref_text FROM table WHERE page = ?",[NSNumber numberWithInteger:page]];
if ([rs next]) {
//this is where I get the string
}
}];
return @""; //And this is where I need to return it, but I can't get it to work
}
我不知道为什么这对我来说很难掌握,但我需要能够对结果集中的字符串做些什么。通常,我会把它归还,但那不会飞到这里。有人可以对此有所了解吗?
由于
编辑:我正在调用我的数据库访问对象,希望返回一个特定的值。很多这些调用都将在后台线程上运行,所以我使用这个数据库队列是线程安全的。我已经更新了sql查询的上下文,以显示我需要做的事情。
答案 0 :(得分:7)
看来你的问题归结为“如何从块内返回一个值回调用函数?”它实际上相当简单,只要块同步执行即可。只需使用__block
变量并分配给它。
__block NSString *result = nil;
[queue inDatabase:^(FMDatabase *db) {
// I'm assuming this is synchronous, because I'm not familiar with the API
FMResultSet *rs = [db executeQuery:@"SELECT ref_text FROM table WHERE page = ?", [NSNumber numberWithInteger:page]];
if ([rs next]) {
result = [[rs acquireStringSomehow] retain];
}
}];
return [result autorelease];
注意,保留是因为可能有一个自动释放池包裹在块周围,我们需要确保该值仍然存在(然后我们可以在块之外自动释放它)。
如果该块是异步执行的,那么您不可能从调用函数返回值。如果你需要处理这种情况,那么你需要将值交回适当的线程以便以后处理,例如。
NSString *str = [rs fetchStringSomehow];
dispatch_async(dispatch_get_main_queue(), ^{
processString(str);
});
答案 1 :(得分:4)
我认为你错过了同步和异步执行之间的区别。我不熟悉您使用的队列API,但我会说您插入到DB队列中的块不会立即同步执行。它在稍后的某个时间点异步执行,然后才会生成结果字符串。
您的getReferenceForPage
方法有两个选项:使其同步,或者通过阻塞使其同步,直到结果字符串可用。第一种选择更简单,更令人满意。有几种方法可以实现它,其中一种方法是在可用时传递一个块来使用字符串:
typedef void (^StringConsumer)(NSString*);
-(void) getReferenceForPage: (NSInteger) page consumer: (StringConsumer) consumer
{
[queue inDatabase:^(FMDatabase *db) {
FMResultSet *rs = [db executeQuery:…];
if ([rs next]) {
if (consumer)
consumer([db getResultString]);
}
}];
}
// and in calling code:
[self getReferenceForPage:1 consumer:^(NSString *reference) {
NSLog(@"Got reference: %@", reference);
}];
另一种选择是在字符串可用时调用已知方法,请参阅Kevin的回答。