Documenting my journey of becoming an iOS developer. This post explains the concept of closures: what they are and what are they useful, as well as how they work under the hood in terms of memory management.

Check out this post on memory management, if you get lost in that aspect of this post.

(Coming Soon)

A closure is a block of code that can be utilize throughout your application. Sound familiar? A closure is a special case of a function. However, unlike a function, closures have multiple syntaxes and functionalities that make them expressive, and you as the programmer can utilize their expressiveness to write elegant code. For example, A closure does not have to have a name associated with it, sometimes known as anonymous functions (for example in JavaScript) due to this nature. Although nameless, they can be assigned to variables, and thus like variables, closures have types which is of course dictated by what the closure returns

Moreover, closures don’t have parameter names, you only specify the types of the parameters. How do you use the parameters? You can assign variables local to the closure for each of your parameters which then you can utilize throughout the closure definition. Or you can use “$0” (1st argument to closure), “$1”(2nd argument to closure), etc.

You can also call a closure right after defining it, and the return value would be stored in the variable that was assigned to the closure.

Closures can be assigned to a variable, be passed as an argument to a function, or be returned from a function, thus closures are also high order functions.

Moreover, closured have the functionality of implicit return values, meaning that if your closure returns a type and the type is returned in one statement, you can get rid of the return keyword, and swift would implicitly return the type internally.

 A closure can encapsulate data from the context (scope) in which the closure was declared in, more accurately, closures captures data into the heap by adding another reference count to the data. You can also change this behavior.

Since closures are associated to variables and constants, closures can also encapsulate closures, but closures cannot encapsulate “regular functions” or classes, although you can call functions and classes within closures.

Closures (like functions or objects) in swift are reference types. What does this mean? It means that they are stored in the heap. This entails that you can assign variables to a closure and call those variables like you would a function; the variable assign to the function does not “contain” the function itself like a variable would “contain” an integer or string, rather the variable “contains” the address of the function in memory. Hence, it is a reference type. Moreover, this allows for the encapsulation of data because all data associated with the function will also be in memory (the heap). By default, this data will stay in the heap as long as the closure is also in the heap. In other words, the closure and anything that it references will stay in the heap as long as the closure stays in the heap.

Additionally, from assigning variables to closures, you can also put them in Arrays, Dictionaries, and treat them like other reference types.

Since closures can be passed in as arguments to functions, then what is the difference between a closure and a callback function?

Simply, callback functions are functions that are passed in as arguments to other functions. They serve the purpose of “communication” for example, a function becomes a callback function when it is invoked by another function. Call back functions are often use for asynchronous tasks, where the callback function gets executed once something else happens, for example a timer runs out. Since, a closure is a special case of a function, A closure can take the form of a callback function. Sticking to definitions and functionalities. A callback function is a closure if it binds(encapsulates) variables in the environment in which it was defined. A common use of closures as call back functions in swift are completion handlers these are also known as escaping closures which are closures that outlive the context in which they were declared in. Moreover, they are used as asynchronous events such as fetching data from a server.

Since closures are in the heap. What does this mean for local variables assigned to the arguments within the closure. By default, these local variables are strong pointers, but can also be declared as unknow or weak via a capture list within the closure. As a result, you break the strong references between the closure and its local variables, meaning that data associated with those local variables may be deallocated from the memory, and thus potentially not be available within the closure. Since weak and unowned variables do not increase the reference count of the data they are associated with(Checkout ARC, Automatic Reference Counting).

Train Tracks aka Side Note:  (Automatic Reference Counting)

ARC is essentially swift memory management. Swift deallocates data from memory when it has zero strong references to it. The slight difference between weak and unowned variables are, Weak variables entail that they can eventually become nil while unowned variables do not have that added functionality, so you as the programmer have to make sure that the data associated with unowned variables within the closure will persist along with the closure, or you can run into trouble such as dangling pointers.

Back To Closures:

Why would you use a closure?

  • A good way to reuse code so you won’t have to copy and pace code all over your application and have single source to come to debug or edit instead of having to go through all your apps file to edit or debug the copy and paste fragments of code. (i.e excellent to make your app robust), after all a closure is just a special case of a function
  • Can be used as helper functions, i.e. callback functions or completion handlers

Summary:

  • Closures are just a special case of a function with expressive syntax that allows you to write elegant code
  • Closures can hold on to data within the context that the closure was assigned to this is known as encapsulation
  • Due to the ability of closures to encapsulate data, closures are predominately used as completion handlers in swift, otherwise known as callback functions

References:

Stanford iOS 9 – Lecture 7. Closures, Extensions, Protocols, Delegation, and ScrollView

The Ultimate Guide To Closures In Swift

https://learnappmaking.com/closures-swift-how-to/