Search code examples
swiftlazy-loadinglazy-initialization

Is there a way to tell if a lazy var has been initialized?


I don't want to initialize a view controller until I need to display its view., so I have it in a lazy var like:

lazy var foo: NSViewController! = {
    let foo = NSViewController()
    foo.representedObject = self.representedObject
    return foo
}()

// ...

override var representedObject: Any? {
    didSet {
        if foo != nil {
            foo.representedObject = representedObject
        }
    }
}

self.representedObject is set before foo is ever referenced, but every time I call if foo != nil, it initializes foo :c

Is there any way I can test if foo has already been set?


Solution

  • lazy is just a convenience wrapper around one specific lazy-instantiation pattern (and one that is only moderately useful). If you want your own pattern, don't use lazy; just build it yourself.

    private var _foo: NSViewController? = nil
    var foo: NSViewController {
        if let foo = _foo {
            return foo
        }
    
        let foo = NSViewController()
        foo.representedObject = self.representedObject
        _foo = foo
        return foo
    }
    
    // This can be private or public, as you like (or you don't technically need it)
    var isFooLoaded: Bool {
        return _foo != nil
    }
    
    override var representedObject: Any? {
        didSet {
            if !isFooLoaded {
                foo.representedObject = representedObject
            }
        }
    }
    

    This is designed to follow the isViewLoaded pattern, which addresses the same basic problem.