ios - 如何避免嵌套 block

标签 ios objective-c cocoa-touch objective-c-blocks grand-central-dispatch

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];
    

    最佳答案

    好吧,我没有麻烦匹配您的右括号,但是这里只是使用return的尝试,您也可以在块内自由使用并稍微减少嵌套:

    [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或其他文档工具,而不必希望了解嵌套的未文档化块的混乱情况。

    只有让它变得疯狂,它才会变得疯狂。

    关于ios - 如何避免嵌套 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18311840/

    相关文章:

    ios - 如何在 ios 中的弹出 block 上添加 UIImageView

    iphone - 释放在类方法初始化中分配的内存

    iphone - 符合iOS4

    cocoa-touch - 在 viewDidUnload 中释放 View

    iphone - 在 Objective-C XCode 中将常量链接到 pch 时出错

    ios - CABasicAnimation + UIBezierPath

    objective-c - 在 Objective-C 中,如何使变量可以从多个类访问

    ios - 如何在 iOS 7 中控制表格部分标题的缩进?

    ios - 模态显示的 UIViewController 在设备旋转时自行消失

    ios - Swift Segmented Control Change Index Event,TableView 不更新