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?
You indicate a lazy stored property by writing the lazy modifier before its declaration. 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.
Variables and constants do not require initialization when declared. However, the variable or constant requires type annotation so that when the compiler reads the code line-by-line, it can determine the data type at the time of the build. A Use of undeclared type error will be thrown otherwise.
You can't make it lazy let because lazy properties must always be variables. Because the actual value is created by evaluation, you need to declare its data type up front. In the case of the code above, that means declaring the property as Int .
Another problem is that lazy var is not thread-safe which means the closure can get executed multiple times due to accesses from different threads.
A shorter version that uses Swift's built-in lazy semantics:
struct Foo {
lazy var bar: Int = {
hasBar = true
return 123
}()
private(set) var hasBar = false
}
Just check for hasBar
instead.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With