This website uses cookies to ensure you get the best possible experience. See our Cookies Policy.

PMG Digital Made for Humans

Using Blocks in Objective-C

6 MINUTE READ | March 25, 2012

Using Blocks in Objective-C

When iOS 4.0 was released, Apple added a new feature to Objective-C, commonly referred to as a parlance block, or just a block. In computer science, blocks are known as lexical closures, but if you’re not a computer scientist, like me, you can just think of it as a function that can be passed as a parameter. In fact, even though blocks can be used in a strictly pure C context, they are actually Objective-C objects. That means that any block can actually be copied, retained and passed around just like any object.

Cocoa Touch Implementation of Blocks

If you’ve done much view animating in Cocoa since iOS 4.0 was released, you may have noticed that there are a few new methods that you can use to perform said animations on a UIView. For example, instead of using the beginAnimations:context: and commitAnimations methods, along with using all of those different methods to set the duration, delay and animation options, you can now use the method animateWithDuration:animations: to perform an animation.

[UIView animateWithDuration:0.25animations:^{self.animatingView.alpha = 0.0;self.animatingView.frame = CGRectMake(124.0, -72.0, 72.0, 72.0);}];

Simply enough, all you have to do is put whatever animations you want performed within the curly brackets and the method will use that block to execute the actual animation. There are two more methods, like that one, that you can use to add a completion block, as well as a delay and animation options for the animation you want to perform.

Anatomy of a Block

As I said before, a block is just a function, or a chunk of executable code, that can actually be passed around like an object. Here is a basic Hello-World block:

^ {NSLog(@”Hello, World!”);}

The caret (^) introduces the block, and the curly brackets enclose the statements that make up the body of the block, in the same way that curly brackets enclose the body of a standard function. Now, how do we actually call this block and execute it? The most common way to use one, is to pass it as a parameter in a method, like we did in the animation method earlier. You can also create one as a variable and pass it around, like this:

void (^helloWorld)(void) = ^ {NSLog(@”Hello, World!”);};

The syntax for declaring a block variable can seem pretty strange, if you’re not used to it. After the assignment (=) we have the actual body of the block, nothing really new here, it’s just the same thing we did before. Before, the assignment is where we actually declare the block variable, which we’ve called helloWorld. The name of the block is always preceded by a caret and wrapped in parentheses. Block variables also have a return type (the first void), as well as a set of parameters that are wrapped in parentheses after the name and before the assignment, just like a standard C function. The block body that you assign to that variable has to conform to the return type of the variable, in our case void, so the block we set here can’t attempt to return anything.

You can then call your block in the same way you would call a standard C function:

helloWorld();

Simple enough, right?

Giving Parameters to your Blocks

Now, for those parameters. Just like functions, a block can take a set of parameters and pass back a return value. Let’s say we want to make a block that we can use to multiply two integers:

int (^multiply)(int, int) = ^(int a, int b) {return a * b;};

Basically, the first int is the return type, then we have the caret and the name of our block variable, multiply, and finally the parameter types wrapped in parentheses. In a way you can think of the declaration of a block variable as the declaration and implementation of a standard C function, they’re just separated by an assignment, or equals symbol.

Now, to call our block. Again, we can just treat it like it’s just a standard C function, just that this time it takes two parameters, and we should probably actually do something with the result of our block.

int result = multiply(2, 3);NSLog(@”2 x 3 = %i”,result);

Blocks as Parameters

Now, as I mentioned a couple of times already, blocks are actually just Objective-C objects, and can be passed into Objective-C methods as simply as any other object. This is actually what we did initially, when calling the animateWithDuration:animations: method. So, let’s write our own method that actually takes a block as a parameter.

@interface MyObject– (void)repeatFor:(int)repetitions withBlock:(void (^)(int repetition))block;@end

@implentation MyObject– (void)repeatFor:(int)repetitions withBlock:(void (^)(int))block{for (int i = 0; i < repetitions; i++) {block(i);}}@end

This method will take the block passed in and execute it for however many repetitions are passed in, passing the current repetition to the block.

To actually perform this method, we pass in the number of times we want it to repeat, and a block we create that just logs the number of times it’s been run each time it gets executed.

[myObject repeatFor:10 withBlock:^(int repetition) {NSLog(@”Ran %i time%@”,repetition,(repetition == 1) ? @”” : @”s”);}];

There you have it, you can now create your very own method that can receive a block as a parameter. A bit weird, and kind of confusing to look at, but once you get used to them, they can be very handy to use.

But, as always, be careful you don’t want to clutter your code with a bunch of unnecessary blocks being passed around. That can make for code that is very difficult to follow. Only use blocks if you’re certain that they’re the best solution for your problem.

Blocks are Time Capsules!

Lastly, I’d like to explain something about blocks that could very easily end up confusing you, let me start by giving you a bit of code:

NSString *string;

void (^helloWorld)(void) = ^ {NSLog(@”%@”,string);}

string = @”Hello, World!”;

helloWorld();

Now, you may look at this and assume that it would print out “Hello, World!”.

Unfortunately, you’d be wrong. It would actually print out absolutely nothing. The reason for this is that a block is actually a Closure. Meaning that a block actually captures its surrounding state, that is it closes around the variables that are in scope at the time it is declared. So, in the case of the above code, when we declare our block, it actually captures the current state of the NSString variable, so when we try to execute the block after changing the value of our NSString, the block still sees it as an empty string.

Insights meet inbox

Sign up for weekly articles & resources.

Now, this may seem kind of pointless in the current example. I mean, why wouldn’t we just set the NSString when we declared it in the first place? But, the fact that a block is a closure can become really useful (or even irritating) when you start passing them around to methods, and the captured state gets passed along with it.


Posted by PMG Advertising Agency

Related Content

thumbnail image

Get Informed

PMG Innovation Challenge Inspires New Alli Technology Solutions

4 MINUTES READ | November 2, 2021

Get Informed

Applying Function Options to Domain Entities in Go

11 MINUTES READ | October 21, 2019

thumbnail image

Get Informed

My Experience Teaching Through Jupyter Notebooks

4 MINUTES READ | September 21, 2019

Get Informed

Trading Symfony’s Form Component for Data Transfer Objects

8 MINUTES READ | September 3, 2019

Get Inspired

Working with an Automation Mindset

5 MINUTES READ | August 22, 2019

Get Informed

Parsing Redshift Logs to Understand Data Usage

7 MINUTES READ | May 6, 2019

Get Inspired

3 Tips for Showing Value in the Tech You Build

5 MINUTES READ | April 24, 2019

thumbnail image

Get Informed

Testing React

13 MINUTES READ | March 12, 2019

Get Inspired

Tips for Designing & Testing Software Without a UX Specialist

4 MINUTES READ | March 6, 2019

Get Informed

A Beginner’s Experience with Terraform

4 MINUTES READ | December 20, 2018

All POST