Swift Lazy and Optional properties

OK, this is an interesting question, and I don't want to imply that the existing answers aren't good, but I thought I'd offer my take on things.

lazy variables are great for things that need to be setup once, then never re-set. It's a variable, so you could change it to be something else, but that kind of defeats the purpose of a lazy variable (which is to set itself up upon demand).

Optionals are more for things that might go away (and might come back again). They need to be set up each time.

So let's look at two scenarios for your side menu: one where it stays around while it's not visible, and another for when it is deallocated.

lazy var sideMenu = SideMenu()

So the first time the sideMenu property is accessed, SideMenu() is called and it is assigned to the property. The instance stays around forever, even when you're not using it.

Now let's see another approach.

var _sideMenu: SideMenu?
var sideMenu: SideMenu! {
    get {
        if let sm = _sideMenu {
            return sm
        } else {
            let sm = SideMenu()
            _sideMenu = sm
            return sm
        }
    }
    set(newValue) {
        _sideMenu = newValue
    }
}

(Note this only works for classes, not structs.)

OK so what does this do? Well it behaves very similarly to the lazy var, but it let's you re-set it to nil. So if you try to access sideMenu, you are guaranteed to get an instance (either the one that was stored in _sideMenu or a new one). This is a similar pattern in that it lazily loads SideMenu() but this one can create many SideMenu() instances, where the previous example can only create one once.

Now, most view controllers are small enough that you should probably just use lazy from earlier.

So two different approaches to the same problem. Both have benefits and drawbacks, and work better or worse in different situations.


They're actually pretty different.

Optional means that the value could possibly be nil, and the user isn't guaranteeing that it won't be. In your example, var menu: NavigationBar? could be nil for the entire lifetime of the class, unless something explicitly assigns it.

Lazy on the other hand means that the assignment will not be called until it is first accessed, meaning that somewhere in code someone tries to use your object. Note however that it is STILL promised to not be nil if you declare it like you have here lazy var menu: NavigationBar = NavigationBar.initialize(), so no need to do optional chaining.

And actually, a variable can be BOTH Lazy AND Optional, which means that it's value will be loaded when it is first accessed, and that value might be nil at the point it's initialized or at any future point. For example:

lazy var menu: NavigationBar? = NavigationBar.initialize()

That NavigationBar.initialize() is now allowed to return nil, or someone in the future could set the menu to be nil without the compiler/runtime throwing errors!

Does that make the difference clear?

Edit: As to which is BETTER that's really a case by case thing. Lazy variables take a performance hit on first initialization, so the first access will be a slow one if the initialization process is long. Otherwise, they're nearly identical in terms of safety/performance. Optional variables you have to unwrap before using and so there is a very minor performance cost with that (one machine instruction, not worth the time to think about)