Dav*_*d U 1 objective-c grand-central-dispatch
我正在试图找出如何让数据库提取在后台运行.以下是同一功能的前景和后台版本.前台版本有效.但在后台版本中,永远不会分配局部变量retval.在pageInfoForPageKey函数中放置一个断点告诉我永远不会调用该函数.
在街区内自助吗?
//foreground version
- (PageInfo*)objectAtIndex:(NSInteger)idx
{
return [[self dataController] pageInfoForPageKey:[[[self pageIDs] objectAtIndex:idx] integerValue]];
}
//background version
- (PageInfo*)objectAtIndex:(NSInteger)idx
{
__block PageInfo* retval = nil;
__block NSInteger pageID = [[[self pageIDs] objectAtIndex:idx] integerValue];
dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(aQueue, ^{
retval = [[self dataController] pageInfoForPageKey:pageID];
});
return retval;
}
Run Code Online (Sandbox Code Playgroud)
通过使用dispatch_async,您告诉系统您希望它很快就能运行您的块,并且您不希望在dispatch_async返回之前等待块完成(甚至启动).这是异步的定义.这就是"在后台"的定义.
系统正在执行您告诉它的操作:它正在安排您的块运行,然后它会在块运行之前立即返回.所以块没有retval在你之前设置return retval,因为块还没有运行.
如果要在后台运行数据库提取,则需要更改API以便retval在块运行后稍后将其传回(对任何需要它的人).一种方法是将完成块作为消息参数传递.这是在后台执行提取的常见模式.例如,看看+[NSURLConnection sendAsynchronousRequest:queue:completionHandler:].
你可以这样做:
- (void)fetchObjectAtIndex:(NSIndex)idx completion:(void (^)(PageInfo *))block {
block = [block copy]; // unnecessary but harmless if using ARC
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSInteger pageKey = [[[self pageIDs] objectAtIndex:idx] integerValue];
PageInfo* pageInfo = [[self dataController] pageInfoForPageKey:pageKey];
dispatch_async(dispatch_get_main_queue(), ^{
block(pageInfo);
});
});
}
Run Code Online (Sandbox Code Playgroud)
然后,您需要更改调用者objectAtIndex:以使用此新API.
| 归档时间: |
|
| 查看次数: |
1154 次 |
| 最近记录: |