Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do structured programming using blocks in Objective-C

When using methods which return blocks they can be very convenient. However, when you have to string a few of them together it gets messy really quickly

for instance, you have to call 4 URLs in succession:

[remoteAPIWithURL:url1 success:^(int status){
    [remoteAPIWithURL:url2 success:^(int status){
        [remoteAPIWithURL:url3 success:^(int status){
            [remoteAPIWithURL:url2 success:^(int status){
            //succes!!!
            }];
        }];
    }];
}];

So for every iteration I go one level deeper, and I don't even handle errors in the nested blocks yet.

It gets worse when there is an actual loop. For instance, say I want to upload a file in 100 chunks:

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

This feels very unintuitive, and gets very unreadable very quick.

In .Net they solved all this using the async and await keyword, basically unrolling these continuations into a seemingly synchronous flow.

What is the best practice in Objective C?

like image 903
Toad Avatar asked Nov 09 '12 14:11

Toad


People also ask

How do you write blocks in Objective-C?

^blockName: Always remember that the block name is preceded by the ^ symbol. The block name can be any string you like, just like you name any other variable or method. Remember that both the ^ and the block name are enclosed in parentheses ().

What is __ block Objective-C?

__block is a storage qualifier that can be used in two ways: Marks that a variable lives in a storage that is shared between the lexical scope of the original variable and any blocks declared within that scope. And clang will generate a struct to represent this variable, and use this struct by reference(not by value).

How do I run an Objective-C program?

In order to run Objective-C program on windows, we need to install MinGW and GNUStep Core. Both are available at https://www.gnu.org/software/gnustep/windows/installer.html. First, we need to install the MSYS/MinGW System package. Then, we need to install the GNUstep Core package.


1 Answers

Your question immediately made me think of recursion. Turns out, Objective-c blocks can be used in recursion. So I came up with the following solution, which is easy to understand and can scale to N tasks pretty nicely.

// __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();
like image 86
gardenofwine Avatar answered Oct 23 '22 10:10

gardenofwine