Home > Blockchain >  False error? `Variable used before being initialized` DURING initialization in init()
False error? `Variable used before being initialized` DURING initialization in init()

Time:02-14

Sorry for the non-sense example. Tried to simplify it, still don’t get what’s going on. The following gives me Variable 'self.greeting' used before being initialized:

struct MyView: View {
    @State var greeting: String
    var length = Measurement<UnitLength>(value: 5, unit: UnitLength.miles)
    init() {
        greeting = "Hello, World!" // Variable 'self.greeting' used before being initialized
    }
    var body: some View {
        Text(greeting)
    }
}

While this is working fine (var length differs; otherwise identical):

struct MyView: View {
    @State var greeting: String
    var length = 5 // now Int
    init() {
        greeting = "Hello, World!"
    }
    var body: some View {
        Text(greeting)
    }
}

Also, this is working (here I removed the @State):

struct MyView: View {
    var greeting: String // @State removed
    var length = Measurement<UnitLength>(value: 5, unit: UnitLength.miles)
    init() {
        greeting = "Hello, World!"
    }
    var body: some View {
        Text(greeting)
    }
}
  • If the compiler wants me to initialize greeting before init() where would that be? preinit()?
  • Why does it think greeting is being “used” uninitialized when actually I am initializing it here?
  • Is there a different way to initialize @State vars? If so, why does it work when the unrelated var length is of Int rather than Measurement?

CodePudding user response:

This code:

@State var greeting: String

Creates a backing variable behind the scenes:

let _greeting: State<String>

If you want to initialize it yourself in init(), you can do:

init() {
    _greeting = new State<String>(initialValue: "Hello, World!")
}

but since you have a constant, it is simpler to set it like this:

@State var greeting: String = "Hello, World!"

The 3rd variant works, because without @State there's no magic.

The 1st option doesn't work, because the code gets translated to:

init() {
    self._greeting.wrappedValue = "Hello, World!"
}

and _greeting is not initialized at this point (no initialValue is specified). Yes, the error is misleading.

I don't know why the 2nd version works. No initialValue is specified, and the String has no implicit default value. Maybe this is a new feature of iOS 15 SwiftUI that should work, but doesn't work in all cases due to some limitations?

P.S. There is something like "preinit": all properties that are assigned with some expressions like length = Measurement<UnitLength>(...) are run there before init, but there's no access to it, it is internal.

  • Related