Blocks can be a really confusing concept and they’re further obfuscated by the crazy syntax. So crazy there’s a website just for the syntax.
Here’s one way to think about blocks.
If you’ve ever worked in a corporate office before, you know about making decks (powerpoint presentations) as I did in my former life.
- When your team needs to build a deck, your manager probably tells you to help him with a couple slides for the story he’s going to tell. He’s the architect but he doesn’t make graphs. So he IM’s you to make them and to tell him when you’re done. (Message one sent.) While he’s waiting for you, he’s continuing to work on other parts of the slide, so that he’s ready when you come back with the data.
- Let’s say that you can only make these fancy looking graphs for him and you don’t know what he’s going to do with it. This time, the data he needs is outside your normal scope. So you call up your friend over in finance to get the right numbers and ask him to email it to you. (Message two sent.) While he’s digging those out for you, you figure out how you want to display the data on the chart.
- Your friend get the data and emails it back to you.
- You take the data and put it in the graphs and send it to your manager.
- Your manager takes your graphs and puts it in the slide.
Congratulations! You’ve just used blocks.
Here’s what it would look like in code.
You have the Manager, Analyst, and DataAnalyst classes.
What does the manager need to do?
To the outside, the manager knows how to make decks, but they don’t know how the decks are made.
Manager.h
#import <Foundation/Foundation.h> @interface Manager : NSObject - (void)makeDeck; @end
Manager.m
// // Manager.m // blockAnalogy // // Created by Xida Zheng on 11/8/14. // Copyright (c) 2014 xidazheng. All rights reserved. // #import "Manager.h" #import "Analyst.h" @interface Manager () @property (strong, nonatomic) Analyst *analyst; @end @implementation Manager - (void)makeDeck { //make the start of the deck [self getGraphsFromAnalyst:self.analyst withCustomStyling:^(NSArray *graphs) { //any custom styling required for this deck }]; //make the rest of the deck } - (void)getGraphsFromAnalyst:(Analyst *)analyst withCustomStyling:(void (^)(NSArray *))customStyling { [analyst makeGraphsWithSpecifications:[NSDictionary new] CompletionEmail:^(NSArray *graphs) { //standard graph handling (i.e. put the graphs on slides) customStyling(graphs); }]; //make the rest of content on the slides with graphs } @end
In order to make the deck, the manager, needs their analyst to get graphs and passes those graphs through any custom styling instructions before the slide makes it into the deck.
(Step 1.) Calling [analyst makeGraphsWithCompletionEmail…] is like IM’ing the analyst to make the graphs. The manager provides the analyst with specifications for the graphs and instructions for when the analyst is done.
What does the analyst do with that information?
(Step 2.) He takes it and translates the conversation with his manager into an algorithm to make the slides and a data request for his friend.
(Step 4.) After he receives a response back, he turns the data into graphs based on his manager’s specifications and send the graphs back to his manager via email.
// // Analyst.m // blockAnalogy // // Created by Xida Zheng on 11/8/14. // Copyright (c) 2014 xidazheng. All rights reserved. // #import "Analyst.h" #import "DataAnalyst.h" @interface Analyst () @property (strong, nonatomic) DataAnalyst *friend; @end @implementation Analyst - (void) makeGraphsWithSpecifications:(NSDictionary *)specifications CompletionEmail:(void (^)(NSArray *))completionEmail { //turn specifications into a way to make for the graphs //turn specifications into a data request to your friend [self.friend getDataWithSpecifications:[NSDictionary new] CompletionEmail:^(NSString *data) { //apply specifications with data NSArray *graphs = @[data]; completionEmail(graphs); }]; //make other graphs with data you're familiar with } @end
What did the data analyst friend have to do?
(Step 3.) Just take in the specifications from the analyst and send back the data in an email.
// // DataAnalyst.m // blockAnalogy // // Created by Xida Zheng on 11/8/14. // Copyright (c) 2014 xidazheng. All rights reserved. // #import "DataAnalyst.h" @implementation DataAnalyst - (void) getDataWithSpecifications:(NSDictionary *)specifications CompletionEmail:(void (^)(NSString *))completionEmail { NSString *data = @"data"; completionEmail(data); } @end
I hope that helps clarify blocks. Let me know what you thought.
Remember, even though blocks are just funny looking objects, they’re misunderstood, and they deserve some love too.