如何使用Objective-C中的块进行结构化编程

Toa*_*oad 10 lambda continuations objective-c structured-programming objective-c-blocks

当使用返回块的方法时,它们可以非常方便.但是,当你必须将它们中的一些串在一起时,它会很快变得混乱

例如,您必须连续调用4个URL:

[remoteAPIWithURL:url1 success:^(int status){
    [remoteAPIWithURL:url2 success:^(int status){
        [remoteAPIWithURL:url3 success:^(int status){
            [remoteAPIWithURL:url2 success:^(int status){
            //succes!!!
            }];
        }];
    }];
}];
Run Code Online (Sandbox Code Playgroud)

因此,对于每次迭代,我都会更深入一级,我甚至还没有处理嵌套块中的错误.

当存在实际循环时,它会变得更糟.例如,假设我想以100个块的形式上传文件:

- (void) continueUploadWithBlockNr:(int)blockNr
{
    if(blocknr>=100) 
    {
    //success!!!
    }
    [remoteAPIUploadFile:file withBlockNr:blockNr success:^(int status)
    {
        [self continueUploadWithBlockNr:blockNr];
    }];
}
Run Code Online (Sandbox Code Playgroud)

这感觉非常不直观,并且非常快速地变得非常难以理解.

在.Net中,他们使用async和await关键字解决了所有这些问题,基本上将这些延续展开为一个看似同步的流程.

Objective C中的最佳实践是什么?

gar*_*ine 4

你的问题立刻让我想到了递归。事实证明,Objective-c 块可以用于递归。所以我想出了下面的解决方案,它很容易理解,并且可以很好地扩展到 N 个任务。

// __block declaration of the block makes it possible to call the block from within itself
__block void (^urlFetchBlock)();

// Neatly aggregate all the urls you wish to fetch
NSArray *urlArray = @[
    [NSURL URLWithString:@"http://www.google.com"],
    [NSURL URLWithString:@"http://www.stackoverflow.com"],
    [NSURL URLWithString:@"http://www.bing.com"],
    [NSURL URLWithString:@"http://www.apple.com"]
];
__block int urlIndex = 0;

// the 'recursive' block 
urlFetchBlock = [^void () {
    if (urlIndex < (int)[urlArray count]){
        [self remoteAPIWithURL:[urlArray objectAtIndex:index] 
            success:^(int theStatus){
                urlIndex++;
                urlFetchBlock();
            }

            failure:^(){
                // handle error. 
            }];
    }
} copy];

// initiate the url requests
urlFetchBlock();
Run Code Online (Sandbox Code Playgroud)