Swift 2 : Lazy Variable Instantiation

Swift provides the lazy attribute that can be added to a variable declaration to implement lazy instantiation. Lazy instantiation is a common pattern that lets you delay creating an object (or some other expensive resource like a socket connection) until it’s needed.

Consider the following over simplified network connection manager:

Each time you instantiate this class, two new Connection instances are created and assigned to outConnection and inConnection in the initialiser.

Instantiating a Connection object could be extremely slow and resource intensive. In effect, each time you instantiate a ConnectionManager object, you end up with the unintended side effect of creating Connection instances upfront.

The only methods of ConnectionManager that actually use the connections are sendMessage and readMessage, and you may not end up using these methods immediately after instantiating ConnectionManager. Perhaps you require the user to type a message into a text field in your application’s UI, and only send the message when a button is tapped.

Lazy initialisation offers a solution to this problem. You can prefix the inConnection and outConnection variable declarations using the lazy keyword and add the code that instantiates the Connection objects in a closure as follows:

You can also use an instance, or class method to supply the value of the lazy variable as follows:

In this example the reason to use a lazy variable is to defer the creation of a Connection instance until it is actually needed. Another reason to use a lazy variable is if the initial value of the variable depends on the values of other instance variables:

One final point worth noting is that lazy variables are initialised only once. For example:

let c = ConnectionManager(hostName:”Arthur’s Macbook”)
print (“\(c.hostName)”)

“Arthur’s Macbook\n”

print (“\(c.connectionStatus)”)

“Arthur’s Macbook, bytes sent:100, bytes received:200\n”

c.hostName = “Jill’s Macbook”
c.outConnection.bytesTransferred = 500
print (“\(c.connectionStatus)”)

“Arthur’s Macbook, bytes sent:100, bytes received:200\n”

Note that connectionStatus returns the same value, even though the variables it depends on have been updated.