Lazy Closures Using Swift

Delay that heavyweight work

Steven Curtis
3 min readDec 18, 2022


Photo by Adrian Swancar on Unsplash

I’ve previously written an article about Lazy Variables but feel that it doesn’t go into enough detail about closures to set up a property and I’m not that happy about the examples used.

Time has passed. I’m now a better coder. Can I write a better article?

Let’s get into it.


Closure: A self-contained block of functionality that can be passed around

lazy: A keyword indicating that it is a property whose initial value isn’t calculated until the first time it’s used. Must be declared as a variable (with the var keyword)

Using A Closure To Initialize A Property


When you want to set up a property but the initial value is relatively expensive to create, you might want to ensure you do it *just once* and *only when necessary*.

We can do that by **using a closure*.

The Example

If we create some code to read a json file and output a String if the file is successfully read. This isn’t necessary production-ready code for reading a file (hey, it works) but is a good example for this particular article.

final class FileReader {
func readFile() -> String? {
do {
guard let fileUrl = Bundle.main.url(
forResource: "fav",
withExtension: "json"
) else {
let text = try String(contentsOf: fileUrl, encoding: String.Encoding.utf8)
return text
} catch {
return nil

let reader = FileReader()
print(reader.readFile()) // Optional("{ \"favourites\": [] }\n")

If we call readFile repeatedly the system has to go away and read the file multiple times. Since we know that fav.json isn’t going to change (it’s a static file here) in between execution that is rather wasteful indeed!

Using a closure

Here we are using a closure to make sure that we are only reading that file a single time. the lazy keyword means that the closure is only created once and ()