How To: Lazy Computed Properties In Swift

Written by Reinder de Vries on September 6 2017 in App Development

Lazy Computed Properties In Swift

Lazy computed properties make your Swift development more efficient and easier to read. It’s a bit of syntactic sugar around the lazy keyword and computed properties, as you’ll find out in this article.

Here’s what you’ll learn:

  • What computed properties are, and when you should use them
  • What lazy initialization is good (or bad) for…
  • How and why to use lazy computed properties

We all know lazy programmers are the best programmers, so you’ll want to pay close attention in this blog post. What’s that Bill Gates quote again?

I choose a lazy person to do a hard job. Because a lazy person will find an easy way to do it.

Ain’t that the truth! Let’s get to it…

  1. What Are Computed Properties?
  2. How To Use Lazy Initialization
  3. Lazy Computed Properties
  4. Further Reading

What Are Computed Properties?

Y’all know what a property is, right? It’s a variable that’s part of a class object. You use it to store stuff. You also use properties to structure your code better.

Here’s a class that defines 3 properties:

class Person {
    var legs = 2
    var eyes = 2
    var arms = 2

Here’s how you use it:

var person = Person()
person.legs = 3

See how I changed the property legs to 3?

OK, now let’s get into computed properties. Just like functions, computed properties can calculate a value and then return it.

Like this:

class Circle {
    var radius:Double = 0

    var circumference:Double {
        return Double.pi * 2 * radius

That’s a class called Circle with two properties. The first one radius, with type Double, is pretty ordinary. The second property, circumference of type Double, is a computed property.

Instead of storing a value it returns a value by executing a bit of code. In the example above, the circle circumference is calculated as C = 2 π r.

You can now use the above Circle class like this:

var cookie = Circle()
cookie.radius = 42.0

See how you can just type cookie.circumference and get the calculated result of the property?

Computed properties have one downside: every time you access them, they’re re-calculated.

This can be a disadvantage if the value of the property doesn’t change and its calculation is intensive. You’d recalculate the value when you don’t have to! That’s a waste of computer resources.

Is there a way to solve that?

Learn how to build iOS apps

Get started with iOS 12 and Swift 4

Sign up for our iOS development course Zero to App Store and learn how to build professional iOS 12 apps with Swift 4 and Xcode 10.

How To Use Lazy Initialization

OK, let’s talk about initialization for a bit. Every time you create an object in Swift, it’s initialized.

You can describe “initialization” as filling a variable with an initial value. You know an object can have properties, so when you initialize an object, its properties are initialized too.

Let’s say I have a car with an advanced GPS navigation system. When I’m taking the car some place I know well, I don’t need navigation – I can just drive there. However, if I’d just initialize the car, the navigation system would be initialized as well – even if I don’t use it. That’s a waste of resources!

class Car {
    var navigation = GPS()

var car = Car()
// car.navigation is now initialized too :-(

How can I use my car’s resources more sensibly? With lazy initialization!

With lazy initialization, also called lazy loading, the initial value of a property is only calculated when it’s first used. If it’s not used, it’s not calculated.

Lazy initialization is helpful in two scenarios:

  • When the value of the property is dependent on factors unknown at initialization of the object
  • When the initial value of the property requires complex computations or is intensive to calculate

In both scenarios it doesn’t make sense to initialize the property when the object is initialized, so that’s when you use lazy initialization.

Using lazy initialization is easy: simply prepend the property with the lazy keyword. You can only use lazy as a variable, so with var and not with let.

Like this:

class Car {
    lazy var navigation = GPS()

Why don’t you try it out for yourself? Execute the code below in Xcode, Playgrounds or a Swift Sandbox. First, run the code with lazy. Then, remove the lazy and see the difference in output.

class GPS {
    init() {
        print("Initializing GPS...")

class Car {
    lazy var navigation = GPS()

var car = Car()

When you run the above code with the lazy property navigation, that Initializing GPS... isn’t printed when car is initialized on the last line. When you remove lazy, the property navigation is initialized when car is initialized, and therefore it prints Initializing GPS....


So how does this connect back to computed properties? Well… you can’t lazy load computed properties. This, for instance, doesn’t work:

class Circle {
    var radius:Double = 0

    lazy var circumference:Double {
        return Double.pi * 2 * radius

// Output: 'lazy' may not be used on a computed property

See how I made circumference lazy? It doesn’t work…

Learn how to code your own iOS apps by mastering Swift 4 and Xcode 10 » Find out how

Lazy Computed Properties

There’s a trick, however, to make lazy computed properties. Here, check this out:

class Circle {
    var radius:Double = 0

    lazy var circumference:Double = { [unowned self] in
        return Double.pi * 2 * self.radius

A few things have changed:

  • The property circumference uses lazy initialization with the lazy keyword
  • The circumference property now uses a closure to calculate the circumference of the circle
  • The closure uses a capture list to access the property radius on self

The closure itself is invoked when the circumference property is accessed, because of that last (). Because it’s lazy, the closure is only executed once when the property is accessed for the first time. That’s a lazy computed property!

The trick is combining a closure and lazily invoking it. When you access the circumference property you implicitly call the closure, and get its result.

Quick Tip: Lazy computed properties are only calculated once: when they’re first accessed. Depending on your code, and code you work with, this is a Good Thing or a hidden cause of weird bugs!

Lazy computed properties come in handy in a few scenarios:

  • When it doesn’t make sense to set an initial value when initializing the object, for instance because it depends on unknown outside factors.
  • When a computed property is computationally intensive, for instance when it calculates something complex

Lazy computed properties also have another added benefit: syntactic sugar.

Sometimes it’s just nicer and more elegant to define a property as a lazy computed property, instead of writing it as a function. After all, you can code a function in such a way that it’ll only recalculate a returned value if it hadn’t done so before – right?

Keywords like lazy, and closures, can add to the readability and maintainability of your code. With lazy computed properties you can keep your code closer together, adding a property’s logic near the property declaration itself. Neat!

Further Reading

Lazy computed properties – so now you know!

Lazy initialization postpones initializing a property until it’s first accessed. Using the lazy keyword isn’t allowed for computed properties, so you use an implicitly invoked closure to get the same effect.

Want to learn more? Check out these resources:

Enjoyed this article? Please share it!

Reinder de Vries

Reinder de Vries is a professional iOS developer. He teaches app developers how to build their own apps at Since 2009 he has developed a few dozen apps for iOS, worked for global brands and lead development at several startups. When he’s not coding, he enjoys strong espresso and traveling.

Leave a Reply

Required to post: Your real name and email address, and a pleasant demeanor. Your email address will not be published. Markdown is supported.

  • Please correct me if I'm wrong, but computed properties are not accessed during initialization. Hence they are automatically loaded lazily!

    1. Reinder de Vries June 14, 2018 11:57 in reply to Mohammad

      That's almost right! They're not loaded lazily automatically, but like you said, they are only executed when accessed, i.e. not during initialization, and also executed during every subsequent read. And that makes all the difference.

      In this article I'm using a closure instead of a computed property. You'd use a computed property for a reasonably simple calculation, like:

      var circumference:Double {
          return Double.pi * 2 * radius

      But what if you want to load data from a database? Imagine you're working with Realm and a table view. The table view reads many times from the Realm data source. When you do that with a computed property, the data is queried every time that property is accessed. Like this:

      class Database
          var items:[String] {
              return getData()
      func getData() -> [String]
          print("I'm executed!")
          return ["Dasher", "Dancer", "Prancer", "Vixen", "Comet", "Cupid", "Dunder", "Blixem"]
      let database = Database()

      The above code calls getData() three times, because items is accessed three times. Consider that you don't want that, because the data doesn't change in-between calls. You'd make items lazy – but you can't, because it's a computed property. So, you turn it into a lazy loaded closure:

      lazy var items:[String] = {
          return getData()

      Now, the getData() function is only called once, even though items is accessed three times. You can still work with it as if it's a computed property, but it's really a lazy loaded property that gets assigned the result of the closure the first time it is called.

  • Sundeep Sharma March 9, 2018 06:12

    very nice. I did not find such a beautiful tutorial on lazy property. Now I have enough knowledge on topic. hoping you write such type of tutorial on other topic also

    1. Reinder de Vries March 9, 2018 13:10 in reply to Sundeep

      Glad you like it! What kind of other topics did you have in mind?