iOS 异步完成块未调用

问题描述 投票:0回答:1

我的代码中的 GCD 有一个非常奇怪的情况,这是一个最小的可重现代码:


- (void)runMyCode {
  __block BOOL completed = NO;
  [self runSomeAsyncAPI:^{
    completed = YES;
  }];
  
  while (!completed) {
    [NSRunLoop.currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
  }
}

- (void)viewDidLoad {
  [super viewDidLoad];

  dispatch_async(dispatch_get_main_queue(), ^{
    [self runMyCode];
  });
}

完成块根本没有被调用。但如果我不使用dispatch_async,它就会起作用。这很奇怪。

ios grand-central-dispatch
1个回答
1
投票

问题在于它将

runMyCode
分派到串行队列,旋转直到设置
complete
为止。因此,在通过
dispatch_async
分派的代码完成之前,分派到同一串行队列的任何其他内容都无法运行。当然,运行循环可以处理事件,但串行队列被占用。
dispatch_after
(将设置
complete
)无法在同一个串行队列上运行。

有多种方法可以解决这个问题:

  1. 运行循环上的旋转是一种早于 GCD 的技术,现在是一种反模式。最好的解决方案是放弃它并采用异步模式。如果我们了解您旋转的原因,我们可能可以提供一些合理的、现代的替代方案。

  2. 您可以对初始

    dispatch_async
    和后续
    dispatch_after
    使用不同的队列。

  3. 您可以使用并发队列(创建自己的队列或使用全局队列)。

© www.soinside.com 2019 - 2024. All rights reserved.