MBulli
MBulli

Reputation: 1709

Lazy readonly property in Swift

While playing a little bit with Swift I tried to write a readonly and lazy initialized property. I quickly wrote that line of code just to learn that it's not allowed.

// no valid Swift code.
lazy let foo : Int = { return 42 }()

You have to declare lazy properties as var. The swift book clearly states that let with lazy is not possible for a good reason:

“You must always declare a lazy property as a variable (with the var keyword), because its initial value might not be retrieved until after instance initialization completes. Constant properties must always have a value before initialization completes, and therefore cannot be declared as lazy.”

Supposing I would like to have a readonly lazy property in swift. What's the best way to archive that?

Upvotes: 28

Views: 10642

Answers (4)

Ilias Karim
Ilias Karim

Reputation: 5371

You need to declare the property at initialization time for it to be immutable.

class Class {
  let foo: Int
  init() {
    self.foo = 42
  }
}

Upvotes: -1

kevin
kevin

Reputation: 2071

Its possible to do this with a computed property and a private struct. There is no need for the lazy keyword on the static var value, as assigning it the result of a block is implicitly lazy.

var foo: Int {
    struct Holder {
        static var value = { return 42 }()
    }
    return Holder.value
}

Upvotes: 5

David Berry
David Berry

Reputation: 41226

You can also use a private backing variable that initializes lazily:

var foo : Int { return _foo }
private lazy var _foo :Int = { return 42 }()

Upvotes: 9

Antonio
Antonio

Reputation: 72760

If readonly and private are synonyms for you in this specific case, then you can make the setter private by explicitly declaring it:

private(set) lazy var foo : Int = { return 42 }()

That's a good compromise between immutability and laziness.

Upvotes: 49

Related Questions