如何避免嵌套块 [英] How to avoid nested blocks

查看:307
本文介绍了如何避免嵌套块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

GCD和块是如此漂亮和方便。但是当我爱上它时,我发现了坏事发生了。看下面的代码:

GCD and blocks are so nice and convenient. But when I fall in love with it, I found that something bad happened. Look at these codes below:

[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];
                  }
                }];
              }
            }];
          });
        }
      }];
    });
  }
}];

疯了?是。我在这麻烦。

Crazy? Yes. I am in this trouble.

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

Did someone have any experience avoiding nested blocks like this?

感谢各位。确切地说,我们有更优雅的方式来做到这一点。例如:

Thanks guys. Exactly, we have more elegant ways to do this. Such as:


  • 事先声明块

  • 将子块设置为独立函数

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

But what I expect is a general solution. Maybe like this:(Pseudo code below)

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


推荐答案

关闭大括号,但这里是一个尝试,通过简单的使用return,你可以自由地使用块和剪切嵌套一点:

Well, I haven't bothered matching your cloud of closing braces, but here's a try by simply using return, which you can use freely inside blocks too and cuts the nesting a little:

[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];
          }];
        }];
      });
    }];
  });
}];

此外,没有人强迫你写入块 inline ,你可以声明它们作为之前的正常变量,以后再使用它们。事实上,如果您的API对其用户很宽松,即使不需要完成任何工作,您也可以重复使用它们,以便在您能够重用之前声明块:

Also, nobody forces you to write blocks inline, you can declare them as normal variables before and use them later. In fact, by declaring blocks before you are able to reuse them if your API is lenient towards its users and allows being called repeatedly even when no work has to be done:

- (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或其他文档工具,而不是希望理解嵌套的未记录的块的混乱。

Whenever I see the nest level too high I put the inside blocks as normal methods in the class and simply call them inside the block. The effect is the same, but it looks much cleaner, and it allows you to use appledoc or other documentation tools for each method rather than hoping to understand the mess of nested undocumented blocks.

如果你让它疯了,它只会变得疯狂。

It only gets crazy if you allow it to get crazy.

这篇关于如何避免嵌套块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆