We have a large project where we have some View
's that are being passed data in their initialisers to setup various @State
variables. Recently we added some code to one of these views and the compiler immediately failed to compile it, indicating a compilation failure on a line that had not been changed. After some work to understand the problem we distilled it down to the following examples.
Here is some original code that compiles, it sets the State
variable in the init()
because that matches the much bigger source this was distilled from.
struct SomeView: View {
@State var anInt: Int
init() {
anInt = 5.
}
var body: some View {
Text("Hello \(anInt)")
}
}
Now we add a Date
variable and the compile fails with an error:
struct SomeView: View {
@State var anInt: Int
let date = Date() /* New variable declaration. */
init() {
anInt = 5 /* Compile fails with error: Variable 'self.anInt' used before being initialized */
}
var body: some View {
Text("Hello \(anInt)")
}
}
This obviously caused much confusion here. Now at this point we managed to fix the code by doing this:
struct SomeView: View {
@State var anInt: Int
let date = Date() /* New variable declaration. */
init() {
_anInt = State(initialValue: 5)
}
var body: some View {
Text("Hello \(anInt)")
}
}
However it doesn't explain why the compilation failed in the first place. Nor is it great as it feels like we're going backwards when it's perfectly ok to just set anInt = 5
with the latest compilers.
We'd like, if possible, for a Swift compiler engineer to take a look and give us an explanation (so we can better understand the issue) and possible improve the error reporting in future compiler releases. Currently we think it's something to do with Date
being a ReferenceConvertable
as swapping in other ReferenceConvertable
's also trigger the same compiler error.