如何避免嵌套块(How to avoid nested blocks)

2019-10-18 12:36发布

GCD和块是这么好,方便。 但是,当我爱上了它,我发现,一些糟糕的事情发生。 看看下面这些代码:

[self functionA:^(BOOL success) {
  if (success) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
      [self functionB:^(NSError *error) {
        if (error != nil) {
          dispatch_async(dispatch_get_main_queue(), ^(void) {
            [self functionC:^(id result) {
              if (result) {
                [self functionD:^(BOOL success) {
                  if (success) {
                    [self DoSomething];
                  }
                }];
              }
            }];
          });
        }
      }];
    });
  }
}];

疯? 是。 我在这麻烦了。

是否有人有任何避免这样的嵌套块的经验吗?

编辑:

多谢你们。 没错,我们有更优雅的方式来做到这一点。 如:

  • 声明块预
  • 让子块作为独立的功能

但我想到的是一个通用的解决方案。 也许是这样的:(伪下面的代码)

functionA.flat.success = [self functionB];
functionB.flat.isntnil = [self functionC];
functionB.flat.error = {};
functionC.flat.isntnil = [self functionD];
[flat call:functionA];

Answer 1:

嗯,我没有打扰符合右括号的云,但这里的一个尝试通过简单地使用回报,这可以在里面块太随意使用,并切断嵌套一点:

[self functionA:^(BOOL success) {
  if (!success)
    return;

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
    [self functionB:^(NSError *error) {
      if (!error)
        return;

      dispatch_async(dispatch_get_main_queue(), ^(void) {
        [self functionC:^(id result) {
          if (!result)
            return;

          [self functionD:^(BOOL success) {
            if (!success)
              return;

            [self DoSomething];
          }];
        }];
      });
    }];
  });
}];

此外,没有人强迫你写内嵌块,你可以宣布他们像以前一样正常的变量,并在以后使用它们。 事实上,通过声明块,你可以重新使用之前,如果您的API是实现其用户的宽松,允许被称为多次,即使没有工作也要做:

- (void)foo:(Bar*)bar
{
    // Prepare the success handler.
    void (^successBlock)(Bar*) = ^(Bar *bar) {

        [[NSNotificationCenter defaultCenter]
            postNotificationName:@"barUpdated"
                          object:bar];
    };

    if (!bar.didAlreadyFetchStuff) {
        [self wellYouBetterFetchSomething:bar withSuccess:successBlock];
    } else {
        // Oh, fake we already did the work.
        successBlock(bar);
    }
}

每当我看到鸟巢水平太高,我把里面块作为分类标准的方法和简单地称他们为块内。 其效果是一样的,但它看起来清爽多了,它可以让你使用appledoc或其他文档工具为每个方法,而不是希望了解嵌套无证块的混乱。

它只有当它变得疯狂变得疯狂。



文章来源: How to avoid nested blocks