False error? `Variable used before being initialized` DURING initialization in init()
Asked Answered
B

1

5

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?
Bonne answered 13/2, 2022 at 13:31 Comment(3)
See this. I have no idea why changing it to var length = 5 works though. It shouldn't work in my opinion.Demented
Apparently this is outdated. “It's not an issue nowadays to set a default value of the @State variables inside the init method. But you MUST just get rid of the default value which you gave to the state and it will work as desired” – 2022-02-12 https://mcmap.net/q/125478/-swiftui-state-var-initialization-issue (so my example should work, as it does in the version with the Int-length)Bonne
Even if we did it wrong I see the error message is weird for this reason "Why does it think greeting is being “used” uninitialized when actually I am initializing it here?"Diamonddiamondback
C
7

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.

Carolacarolan answered 13/2, 2022 at 14:44 Comment(1)
Thanks for the insight! Very interesting. According to Mojtaba Hosseini in https://mcmap.net/q/125478/-swiftui-state-var-initialization-issue it should be possible to set the @State var in the init using it’s non-prefixed name. So, I would assume Apple added an incomplete feature which doesn’t work for structs/Views with Measurements (and more?) in it.Bonne

© 2022 - 2024 — McMap. All rights reserved.