【问题标题】:CFRunLoopRunInMode() within AFHTTPClient success and failure blocksAFHTTPClient 成功和失败块中的 CFRunLoopRunInMode()
【发布时间】:2013-04-15 20:28:45
【问题描述】:

我正在尝试使用CFRunLoopRunInMode() 来避免在[AFHTTPClient getPath:...] 完成块中返回。

我的代码如下:

NSLog(@"start");
__block BOOL someCondition = NO;
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://domain.com"]];
[client getPath:@"my/path" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"success");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"async log");
        someCondition = YES;
    });
    while (!someCondition) {
        CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, YES);
    }
    NSLog(@"failure");
}];

我预计输出是:

start
async log
failure

但我只得到:

start

CFRunLoopRunInMode() 返回kCFRunLoopRunHandledSource,但调度队列从不执行提交的块。如果我在完成块之外运行相同的代码,则输出符合预期。

我无法弄清楚为什么从完成块运行时调度队列没有得到处理。

有人能解释一下为什么会发生这种情况吗?

【问题讨论】:

  • 那是完成块。第一个块在 HTTP 请求操作完成时调用,第二个块在请求失败时调用。 - 请注意,尝试等待直到某些异步操作完成通常是一个坏主意,特别是如果它阻塞了主线程并因此阻塞了用户界面。
  • 我喜欢生活在边缘;)说真的,我真的很想知道它为什么会这样。

标签: ios objective-c objective-c-blocks afnetworking cfrunloop


【解决方案1】:

我无法弄清楚为什么从完成块运行时调度队列没有被处理。

因为您没有“运行”调度队列(没有“运行”调度队列之类的东西)。你运行了运行循环。调度队列是相关的,但是是另一回事。在串行队列(如 main)上一次只能运行一个块。在您的块完成之前,不能安排其他块。 GCD 中没有 API 可以规避这一点。这通常是一件非常好的事情,因为它为在 runloop 操作中并不总是存在的队列操作提供了确定性。

【讨论】:

    【解决方案2】:

    AFNetwork 的成功和失败块都调度在主队列中,你写在失败块中的异步块也调度在主队列中。

    在故障块完成之前,您的 GCD 同步块将运行。因为'while'条件永远不会为假,所以失败块永远不会完成,也永远不会有机会被执行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-18
      • 1970-01-01
      相关资源
      最近更新 更多