22

I had this error several times now and I resorted to different workarounds, but I'm really curious why it happens. Basic scenario is following:

class SomeClass {
  var coreDataStuff = CoreDataStuff!
  lazy var somethingElse = SomethingElse(coreDataStuff: coreDataStuff)
}

So I understand I can not use self before class is fully initialised, but in this case I'm using self property coreDataStuff to initialise a lazy var which will not happen until my instance is ready.

Anybody could explain me why I'm getting Instance member can not be used on type error?

66o
  • 756
  • 5
  • 10
  • what is returning `CoreDataStuff()` ? – Tancrede Chazallet Dec 11 '15 at 14:35
  • sorry, typed the code example too fast, it's not returning anything, it's just unwrapped optional that's initialised later on with an instance that manages my core data objects. Just to clarify, the current version of code is the one that gives me an error – 66o Dec 11 '15 at 14:38
  • Perhaps because you haven't used 'self.coreDataStuff'? – Christopher Kevin Howell Dec 11 '15 at 14:40
  • 2
    Possible duplicate of [Instance member cannot be used on type](http://stackoverflow.com/questions/32351343/instance-member-cannot-be-used-on-type) – Losiowaty Dec 11 '15 at 14:41
  • 1
    This is **NOT** the same as [Instance member cannot be used on type](http://stackoverflow.com/questions/32351343/instance-member-cannot-be-used-on-type). This question deals with lazy variables, while the other deals with a get-only variable. Two **very** different things in Swift. – Senseful Jul 07 '16 at 18:04

2 Answers2

32

Try that :

class SomeClass {
  var coreDataStuff = CoreDataStuff!
  lazy var somethingElse: SomethingElse = SomethingElse(coreDataStuff: self.coreDataStuff)
}

It is important to precise the type of your lazy var and to add self. to the argument you pass

Tancrede Chazallet
  • 7,035
  • 6
  • 41
  • 62
  • Can you explain this syntax a bit as it is the first time I see something like that. What's up with passing self as arguments to SomethingElse init? I tried it anyway and it's giving me an error that it's unable to cast self to CoreDataStuff which is normal as SomeClass has nothing to do with CoreDataStuff – 66o Dec 11 '15 at 15:08
  • 1
    Did you add the `somethingElseType` as I wrote ? – Tancrede Chazallet Dec 11 '15 at 15:08
  • Oh wait, I thought `SomethingElse` was a method... my bad – Tancrede Chazallet Dec 11 '15 at 15:11
  • Hehe, I figured it out at the same time, thanks it was helpful. Any idea why swift doesn't complain when I add self. to the coreDataStuff ? – 66o Dec 11 '15 at 15:17
  • I guess that since the context is different (not in a method), it's not obvious that you want the content of `coreDataStuff` and not the "pointer" `coreDataStuff`. And you need to precise the type because since you introduce a "variable" I guess the compiler is unsure of what type it would be since it's lazy. – Tancrede Chazallet Dec 11 '15 at 15:22
9

There are two requirements that are easily overlooked with lazy variables in Swift, and, unfortunately, the warnings are cryptic and don't explain how to fix it.

Lazy Variable Requirements

  1. Use self.: When referring to instance members, you must use self.. (E.g. self.radius.)

    If you forget to use self., you'll get this error:

    Instance member 'myVariable' cannot be used on type 'MyType'

  2. Specify the type: The type cannot be inferred, it must be explicitly written. (E.g. : Float.)

    If you forget to specify the type, you'll get this error:

    Use of unresolved identifier 'self'

Example

struct Circle {
  let radius: Float
  lazy var diameter: Float = self.radius * 2 // Good
//lazy var diameter        =      radius * 2 // Bad (Compile error)
}
Senseful
  • 86,719
  • 67
  • 308
  • 465