1

In this answer, it is suggested to tag properties with lazy in order to define them based on other properties. This seems clean and preferable to suggestions from other SO answers.

However, following this advice still generates the error message: Instance member cannot be used on type error

What's the right way to define tutorial so it can include other properties while using lazy?

class TestViewController: UIViewController {
    let Key1 = "Key1"
    let Key2 = "Key2"
    lazy var tutorial = [Key1, Key2]
}

Created this simple class to test @dfri's suggestion, yet the error still occurs:

import Foundation

class Test  {
    let Foo = "foo"
    lazy var bar = Foo
}
Community
  • 1
  • 1
Crashalot
  • 33,605
  • 61
  • 269
  • 439

1 Answers1

3

Possibly I'm mistunderstanding you, but are you looking for something like the following?

class Foo {
    let Key1 = "Key1"
    let Key2 = "Key2"
    lazy var tutorial : [String] = { [self.Key1, self.Key2] }()
    /* Alternatively:
    lazy var tutorial : [String] = [self.Key1, self.Key2] */
    init() {}
}

Note that I'm accessing the same-class properties using prefix .self.


Alternatively, just use a computed property. In the simple example above, Key1 and Key2 are immutables, so it's really no reason to let tutorial be a lazy, stored property:

class Foo {
    let Key1 = "Key1"
    let Key2 = "Key2"
    /* now as a computed property: */
    var tutorial : [String] { return [Key1, Key2] }
    init() {}
}

If Key1 and Key2 were mutables, however, then the two solutions above would differ:

  • lazy var tutorial would be lazily initialized (upon first use) with the current values of Key1 and Key2, at that time, but not be influenced by later changes in Key1 and/or Key2.
  • Letting tutorial be a computed property, however, would always yield an (computed) array the current values of Key1 and/or Key2.

Edit addition (after edited question):

For the updated example in your question, the the lazy variable is used just in the same way as described above:

class TestViewController: UIViewController {
    let Key1 = "Key1"
    let Key2 = "Key2"
    lazy var tutorial : [String] = [self.Key1, self.Key2]

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
dfrib
  • 70,367
  • 12
  • 127
  • 192
  • Both cause this error: Value of type 'NSObject -> () -> ViewController' has no member 'Key1'. Also why is using `self` necessary? – Crashalot Feb 23 '16 at 18:03
  • The example above should not yield an error in its current form. However in your specific example (which you haven't showed us in your question), it sounds as if you're trying to use a lazy variable in a closure? Possibly add more context of your specific problem to your question. Lazy variables are only to be used class or structure properties. – dfrib Feb 23 '16 at 18:06
  • It's getting used in a ViewController class and defined as a class property, will update with more context but it's basically as you guessed in this answer. Just updated question. – Crashalot Feb 23 '16 at 18:08
  • @Crashalot Are you sure the example you've shown is reflecting what you're trying to implement (which yields error for you). I added an edit to answer your updated example in the bottom of my answer above. – dfrib Feb 23 '16 at 18:15
  • Yes it is. Not sure why this error is occurring, will investigate further. So the only difference between your code and mine is the use of `self`? Why is that necessary anyway? – Crashalot Feb 23 '16 at 18:46
  • Even after creating a test class with nothing but the lazy property and its dependent property, the error still occurs. Does the new code in the question compile for you? – Crashalot Feb 23 '16 at 19:24
  • @Crashalot Pardon the slow answer. In your added example you've left out `self.`: you need to include the prefix `self.` to access same-class properties, for the _instance_ which is guaranteed to be initialized at the first call of any lazy variables. Also, you need to specify the type of the lazy variables, as this cannot be inferred by assignment, due to the delayed lazy assignment. Hence, try `lazy var bar : String = self.Foo` in your example. – dfrib Feb 23 '16 at 19:54
  • OK use of `self` makes sense but updating the Test class above to use `self` gives this error: Use of unresolved identifier 'self' – Crashalot Feb 23 '16 at 19:58
  • @Crashalot Make sure you've specified the _type_ of the lazy variable `bar`, i.e., `lazy var` **bar : String** `= self.Foo`. – dfrib Feb 23 '16 at 19:59