I have searched here. I have seen and assume this is affecting it
Class initialisation in Swift is a two-phase process. In the first phase, each stored property is assigned an initial value by the class that introduced it. Once the initial state for every stored property has been determined, the second phase begins, and each class is given the opportunity to customize its stored properties further before the new instance is considered ready for use.
When I run the below code I get the error Variable 'self.string' used before being initialized.
But it applies to every variable I don't change to a var and initialize. What is going on here?
Here is the error:

The below doesn't work.
struct IntTextField<T: Numeric & LosslessStringConvertible>: View {
@Binding var number: T?
@State private var string: String
private let isDecimalAllowed: Bool
private let title: LocalizedStringKey
private let onEditingChanged: (Bool) -> Void
private let onCommit: () -> Void
public init(_ titleKey: LocalizedStringKey, number: Binding<T?>, isDecimalAllowed: Bool, onEditingChanged: @escaping (Bool) -> Void = { _ in }, onCommit: @escaping () -> Void = {}) {
self._number = number
self.string = "Why doesn't this work????"
self.isDecimalAllowed = isDecimalAllowed
self.title = titleKey
self.onEditingChanged = onEditingChanged
self.onCommit = onCommit
}
var body: some View {
TextField(title, text: $string, onEditingChanged: onEditingChanged, onCommit: onCommit)
.numericText(text: $string, number: $number, isDecimalAllowed: isDecimalAllowed)
.modifier(KeyboardModifier(isDecimalAllowed: isDecimalAllowed))
}
}
The below works (I have to change them all to var and initialize them to something), why do I have to do this?
struct IntTextField<T: Numeric & LosslessStringConvertible>: View {
@Binding var number: T?
// Everything below is changed to var and initialized
@State private var string: String = ""
private var isDecimalAllowed: Bool = false
private var title: LocalizedStringKey = ""
private var onEditingChanged: (Bool) -> Void = { _ in }
private var onCommit: () -> Void = {}
// To here
init(_ titleKey: LocalizedStringKey, number: Binding<T?>, isDecimalAllowed: Bool, onEditingChanged: @escaping (Bool) -> Void = { _ in }, onCommit: @escaping () -> Void = {}) {
self._number = number
self.string = "Why does this work????"
self.isDecimalAllowed = isDecimalAllowed
self.title = titleKey
self.onEditingChanged = onEditingChanged
self.onCommit = onCommit
}
var body: some View {
TextField(title, text: $string, onEditingChanged: onEditingChanged, onCommit: onCommit)
.numericText(text: $string, number: $number, isDecimalAllowed: isDecimalAllowed)
.modifier(KeyboardModifier(isDecimalAllowed: isDecimalAllowed))
}
}
That variable is a little different than normal because of its @State property wrapper. To initialize it here without that error, you need to do this:
self._string = State(initialValue: "Why doesn't this work????")
The _ lets you access string without the property wrapper. In fact, you're already doing this on the line above with your Binding with a similar strategy.
On your second example, string already has a default value of "", so the compiler isn't worried about it not being set yet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With