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
beforeinit()
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 ofInt
rather thanMeasurement
?
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.