Blocks and Closures in Objective-C
Blocks are hard. Conceptually difficult to understand, blocks are nonetheless integral to many facets of Objective-C and other languages. They are made up of chunks of code that can be called and used over and over for a myriad of purposes and contexts throughout your application.
If this sounds similar to methods, then you’re on the right track. Methods and blocks are alike, in regards to being called by classes and within other methods. The main difference is the scope of methods and blocks. Let’s pretend our code is now a three-dimensional model. Methods would be 2D and straightforward in how they work because they are very linear. Blocks would be more 3D in the way they puncture the layers of your classes and code, much in the same way wormholes connect different points of space and time.
The compiler likes to keep a linear thread throughout. At runtime, your application starts at the beginning and goes through the code one line at a time. When it reaches a block, it follows the thread to where the block is defined, no matter if the block is defined in a different class or just a few lines away from the block’s call. If you NSLog inside and out of that block, you can follow where that thread leads.
Let’s try this out for ourselves, shall we? Let’s make a basic sandwich, and allow our application to hand us the ingredients we need in the proper order.
Blocks are ideal for snippets of code that can be run over and over. API requests and animations actually have blocks built in to their methods (completion blocks used as closures to run some code at the time when the request or animation is finished. So if your code has been waiting to do something specific with a request from the internet, the code in the completion block will not run until the request is complete and there is information to go off of. Likewise, if you have an animation and want to do something specific once it’s finished, like fade it to black, you can do so in the closure — the completion block).
I am specifically going to discuss the blocks we call as method parameters, because they are more confusing to understand than the blocks built in to the methods used in the API request-dance and for animations. They are difficult to grasp because it is our job to write both sides — the method that first introduces them, and the one that calls and defines them.
One website, the website that explains how… annoying block syntax can be, is your friend. (If you want something with gentler language, try this one.) It’s a very useful site because you don’t have to memorize block syntax, which takes the burden off a bit from their comprehensive immensity.
In my understanding blocks are hardly ever used as properties or local variables. I’m sure there are proper, perfect situations where a block as a variable is exactly what you need, but that shall be a discussion for later. What we must concern ourselves with now is how blocks are used alongside methods, namely as a method parameter and as an “argument to a method call” (thanks, fuckingblocksyntax!).
When you break it down, a block is full of familiar pieces:
Super familiar, right? We know returnTypes. They’re usually what we capture from methods that call for a return.
We know parameterTypes. They are the arguments we insert into methods so that we can use them inside the method body.
The blockName is just like the name of a method, or an instance variable: it really doesn’t matter what we choose, so long as we know what we’re referring to and that we remain consistent. Good practice, of course, asks that we name it something that makes sense to anyone else looking at our code without needing comments. The blockName is simply a reference to the block we are going to call within the method. Some people name it just “block” or “completionBlock” (since a lot of block methods end with:
Since we recognize all of those pieces, the only unfamiliar one is really that pesky ^ (caret).
Let’s digress a moment to reflect on the caret (^), shall we?
The caret is a widely used symbol, with roots and uses across various disciplines. You may have seen it used in mathematics (as a placeholder for superscript to denote exponents — 8 ^ 2 is the same as 8², which equals 64). Perhaps you have seen it used as an arrow, pointing up at whatever is directly above (or somewhere up there, I’m sure if there are enough ^^^^^^’s they’ll know what I’m pointing at), mostly used in social media. It’s likely you’ve seen it used in another programming language, like in C++ or Smalltalk or Pascal or Go, or to signify the XOR operator.
I like to think of it in more of the proofreading sense. Maybe it’s my writing background, but I’m most comfortable with the caret being used to signify an insertion — be it a word, phrase, punctuation point, or code snippet — into the context of the larger work. To me, the caret is a placeholder for the block we are inserting into the code. Like a handwritten caret, it doesn’t line up with the rest of the work — doesn’t flow like the typewritten text it interrupts — but nonetheless adds a missing component, without which the work cannot be complete. Maybe this is why there are so many completionBlocks — not only do you get to signify what happens in code when the block is wrapping up in said completion, but with it your code becomes a little more whole in its entirety.
A little more about how I think of the carets in the block syntax: when you compare a generic block as a method parameter
to an actual, generic method
what do you see? I see the caret as a sort of stand-in for where the method name should be. Pretty cool, right? It’s like the block is telling you that it can stand-in for a number of different methods, that it can be used in a bunch of different method contexts. It’s free from the context of any specific method and particular use in your code. I like to imagine the block as a sort of astronaut, floating free throughout the code until she’s drawn through the invocation of her block like the wormhole that it is.
Now that we know the syntax to using a block in a method, let’s see another one in action!
Going along with the sandwich theme, I made a block that acts a little like a customer ordering lunch. This block takes a single parameter, a BOOL, which questions whether the customer is vegetarian. If the customer says they are, they get a grilled cheese sandwich. If they’re not, they get a turkey club sandwich.
Blocks are like magic. Imagine yourself as a wizard, and start reciting some incantations! In all seriousness, blocks must be invoked in order to run. It’s the way that they’re called, always in a format that looks like this:
optionalReturnType = blockName(optionalParameter)
As you can see in this example, the block invocation is simply the name of the block, followed by round brackets with a BOOL inside.
Before you expect any block magic to happen, you must say its spell!
The block, hearing its call, will take whatever you give it inside its rounded brackets, carry it over to where the block is defined, and use that information to run through the code within those curly braces (you can always tell a block is finished by that unique crunch of symbols, the }]; ) before returning back to right after you invoked the block, the thread of the program continuing through as though there had been no detour at all.
You can have blocks with multiple parameters. Separate them as you would in an array, with a comma and a space for readability. Some of Apple’s block methods come already with two parameters passed in. It’s usually cleaner and easier to understand to just pass in one argument to a block, so if you decide to do two make sure you’re ready for it or that it will truly make your method less cluttered and complex.
This next example shows you the order the compiler runs the code. You call the block method when you’re ready for it to run (in this case, it’s a sandwich assembly line method to make a certain number of the same sandwich, based on the number you provide it with. Here we want three sandwiches).
The compiler bounces down to the method the code is calling. For each sandwich we ask for, it slaps down some bread, and then we invoke the block!
We return back to the method above and get a list of ingredients in the order we want them to be on our sandwich. That list is returned, and we go back down to the method to finish up the code (so many layers! We’ve already gone from the method pictured above to the one below twice. Blocks. They’re like sewing or weaving, going back and forth until we’re finished — it’ll always be twice like in this example, unless you call more blocks inside these methods. Then the fabric of our code becomes a little more pleated).
In this method below, we pick back up on the line of the block invocation — that array we took with us has been captured by this method. The compiler goes through that array of ordered ingredients and NSLogs them out one at a time in order — hooray for NSArrays and how they keep their order! — and then tops the sandwich off with more bread.
The sandwiches log out as we requested.
The amazing thing about this block we’ve written is that in another method, we can invoke the same block, but instead of returning an array of lettuce, tomato, and turkey, we can return one of bacon, egg, and cheese (or apple and brie, or all the layers of a hoagie), and the block will still print out the layers one at a time in the correct order. This is the beauty of blocks. They have code rendered generic that can be called to work with specific variables.
Here’s a final example of the potential of blocks. This block will be passed a single parameter and will return something when it’s finished. We have a method to make sandwiches for people with specific names and tastes.
We give the method an array of names of the people who want sandwiches (Amy and Tom). For each name in that array (two, in this case), we will call out their sandwich with their name, and start making their individual sandwiches. Bread comes first, and then we need the ingredients — time to go back to the block!
We pass in the name we’re on into the block — Amy — and then check in with what the block says. If the name is Amy, she wants a BLTA with pickles, so that’s the array we return to the method.
Then, like the block we saw above, this method takes each ingredient in order and lays them on top of the bread, then tops it off with more bread.
We go through the same thing with Tom and the program makes his sandwich too. After the array has been completely iterated through, we have as many complete sandwiches as the people who ordered them.
Blocks. They’re quite magical, aren’t they? They’re like wormholes, road detours that show us the sights but still get us where we need to go. In fact, the application wouldn’t be the same without them. Like all difficult concepts, they can really warp your mind, and while you may pray you never need to use them, once you get them — really get them — they can be that missing piece of your program puzzle that makes your app perfect.
Or not. But you can’t deny that they are pretty useful.
If you’re still stuck on how blocks work, don’t fret. They’re complicated, and everyone accepts this. With enough time and effort (and asking a lot of questions), you’ll be able to grasp them enough to use in your program. And when you do, there’s nothing more gratifying.
Until then, they’re still fucking — excuse me, gosh-darned — blocks.