LS.Shanghai LS.Shanghai - 5 months ago 24
Swift Question

Swift weak lazy variable won't compile

To demonstrate this problem, I made a vanilla Cocoa project. Here is the

AppDelegate.swift
:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

weak lazy var isGood : NSNumber? = {
return true
}()

func doSomething() {
let result = isGood!
}

func applicationDidFinishLaunching(aNotification: NSNotification) {
// Insert code here to initialize your application
}

func applicationWillTerminate(aNotification: NSNotification) {
// Insert code here to tear down your application
}
}


Xcode gives this:


unkown :0: error: cannot convert return expression of type 'NSNumber?' (aka 'Optional') to return type 'NSNumber?'

unkown :0: cannot assign value of type 'NSNumber?' to type 'NSNumber??'

unkown :0: cannot assign value of type 'NSNumber?' to type 'NSNumber??'


In my actual project, it's another object of
MyCustomClass
(instead of NSNumber). The error is the same except the type is
MyCustomClass
.

If I remove
weak
or
lazy
from the declaration, it's all fine. But I wanted to save the reference count from being +1, since the
MyCustomClass
is an
NSViewController
which is sure to always be there.

Any idea of how to use the weak lazy variable?

Answer

Weak and lazy do not mix well. The error message is completely useless at explaining what is going on, but essentially lazy and weak are at odds with each other:

  • lazy tells Swift that you don't want your variable created until the first time you access it, but once it is created, you want to keep it indefinitely for future reference, while
  • weak tells Swift that you don't want your variable to be the last link that keeps your variable from being deallocated, which works against the "keep indefinitely" goal of lazy variables.

You can solve this by emulating lazy, like this:

class Foo {

    weak var isGoodCache : NSNumber?

    private var makeIsGood : NSNumber {
        isGoodCache = true
        return isGoodCache!
    }

    var isGood:NSNumber? {
        return isGoodCache ?? makeIsGood
    }
}