Make blocks (closures) your friend (Objective-C and Swift 3)

[Download Xcode project and source code from GitHub to follow along.]

Let’s learn about, formally define, review some code for, and write some code for blocks in Objective-C, and write some code for closures in Swift. Blocks are one of the most important programming language constructs you’ll ever learn about. I depend on them to get notified when concurrent tasks complete (i.e., as callbacks), whether I submitted those tasks synchronously or asynchronously. I’ll bet that even if you have never heard of blocks or closures, you’ve already used them. Guess what? If you’ve been reading this blog, you’ve already used blocks!


Objective-C blocks and Swift closures
Blocks/closures allow you to create chunks of almost any type of code that can be called almost anywhere, anytime (like in the future). They are self-contained but know about local variables around them. They can be assigned to properties, variables, and/or constants — and passed as parameters to functions/methods. Blocks/closures can access variables and constants from the surrounding environment in which they were defined. Even if the variables and constants from their original surrounding environment go out of scope, blocks/closures can still access those variables and constants. Perhaps most importantly, blocks/closures are great for communicating between objects, especially as in the case of reporting completion of an operation (i.e., callbacks). You can define a block/closure one place, but not have it execute until (much) later. So you don’t have to incur the overhead of adopting protocols and encoding calls to delegate methods. Protocols/delegates have their place, but you don’t have to write all the code to implement and adopt them when you just need a simple callback. That’s my take. How are blocks and closures formally defined?

Formal definition

Blocks represent typically small, self-contained pieces of code. As such, they’re particularly useful as a means of encapsulating units of work that may be executed concurrently, or over items in a collection, or as a callback when another operation has finished.

Blocks are a useful alternative to traditional callback functions for two main reasons:

  • They allow you to write code at the point of invocation that is executed later in the context of the method implementation.

    Blocks are thus often parameters of framework methods.

  • They allow access to local variables.

    Rather than using callbacks requiring a data structure that embodies all the contextual information you need to perform an operation, you simply access local variables directly.

Apple’s “Blocks Programming Topics: Conceptual Overview – Usage”

Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages.

Closures can capture and store references to any constants and variables from the context in which they are defined. This is known as closing over those constants and variables. Swift handles all of the memory management of capturing for you.

Apple’s “The Swift Programming Language (Swift 3.0.1): Closures”

#ad

Code where you might not recognize blocks/closures
Here’s my code from my post entitled “Concurrency in iOS: serial and concurrent queues in Grand Central Dispatch (GCD) with Swift 3”, where I submitted image file download tasks on a concurrent queue using Swift 3. See highlighted lines of code 13, 15, 16, 17, 18, 19, 20, 25, 27, 28, 29, 30, 32, 34. These are closures — actually, there’s one larger closure that contains a sub-closure:

Look in Apple’s Grand Central Dispatch (GCD) Swift documentation at the official instance method declaration for “async” (line 4 highlighted):

Apple calls line 4 an “escaping closure:”

A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write @escaping before the parameter’s type to indicate that the closure is allowed to escape.

One way that a closure can escape is by being stored in a variable that is defined outside the function. As an example, many functions that start an asynchronous operation take a closure argument as a completion handler. The function returns after it starts the operation, but the closure isn’t called until the operation is completed—the closure needs to escape, to be called later.


Here’s the Objective-C equivalent of my Swift code using a closure. See highlighted lines of code 7, 9, 10, 11, 14, 16, 17, 18, 20, 22. These are blocks — actually, there’s one larger block that contains a sub-block:

Look in Apple’s Grand Central Dispatch (GCD) Objective-C documentation at the official function declaration for “dispatch_async” (line 2 highlighted):

Apple calls line 2 a “block:”

The block to submit to the target dispatch queue. This function performs Block_copy and Block_release on behalf of callers. This parameter cannot be NULL. …

This function is the fundamental mechanism for submitting blocks to a dispatch queue. Calls to this function always return immediately after the block has been submitted and never wait for the block to be invoked. The target queue determines whether the block is invoked serially or concurrently with respect to other blocks submitted to that same queue. Independent serial queues are processed concurrently with respect to each other.

Writing Objective-C code for blocks
Let’s write some Objective-C code to define and use a block to serve as a callback when an asynchronous, concurrent task completes.

1) Let’s declare a block reference, or… I make extensive use of blocks and find that a block that returns success or failure and returns a string containing a possible error message is applicable to many different situations, I define a block type:

2) Now we define the block, encoding what we want it to do, and pass it as an argument to a method:

3) When our background task for downloading an image completes, it calls our block (completion handler) to inform the caller of success or failure and updates the user interface (UI) on the main thread:

#ad

Download the code and try it out. We’re going to write code for closures in Swift, same Bat-Time, same Bat-Channel, so check back soon. I’ll give you a hint about defining Swift closures:

Go to the next post to see all the code I wrote for defining and executing a Swift 3 closure.

Note that I’m including coverage of Objective-C for a good reason. Remember that a lot of iOS apps today are being written, or originally were written, in Objective-C and are still being actively maintained and updated today. Swift has changed so many times that developers have had to rewrite the same code multiple times. Many Apple iOS frameworks were/are written in Objective-C. While Swift is a promising new language, you should still learn — at least be knowledgeable in — Objective-C. One great advantage with using Objective-C: As new Xcode versions keep coming out, you rarely have to rewrite much code.

#ad

Author: Andrew Jaffee

Avid and well-published author, software engineer, designer, and developer, now specializing in iOS mobile app development in Objective-C and Swift, but with a strong background in C#, C++, .NET, JavaScript, HTML, CSS, jQuery, SQL Server, MySQL, Oracle, Agile, Test Driven Development, Git, Continuous Integration, Responsive Web Design, blah, blah, blah ... Did I miss any fad-based catch phrases? My brain avatar was kindly provided by https://icons8.com under a Creative Commons Attribution-NoDerivs 3.0 Unported license.