If I place a Picker or a Toggle in a SwiftUI Form, the associated label is always visible:
But for a TextField, the label is only shown while the field is empty:
And as soon as I start to fill in the TextField, the label disappears.
So now I have no context for what the TextField is meant for.
This would not be a problem if the TextField content is self explanatory, but I have a form with multiple TextFields used to input numerical values, and once they are filled in I have no context for differentiating between each number.
Is there any way to make a SwiftUI TextField behave like a Picker or Toggle, and have the label permanently displayed?
Update:
After trying out Benzy's answer of using LabeledContent, I get this sort of result when I have multiple fields. As you can see the alignment of the TextFields themselves depends on the length of the text in the LabeledContent. I'd prefer to align the TextFields.
Try wrapping the TextField as LabeledContent:
Form {
Section("Creator") {
LabeledContent("Name") {
TextField("Name", text: $creator, prompt: Text("Name"))
}
}
}

You might prefer to supply an empty prompt and then add styling to the label, for example, to style it like a prompt:
LabeledContent {
TextField("Name", text: $creator, prompt: Text(""))
} label: {
Text("Name")
.foregroundStyle(.secondary)
}

EDIT You were asking in a comment, how to align multiple text fields.
A simple way would be to set a fixed width on the labels. However, if you want the labels to be as wide as the widest label, you could use a ZStack to determine the footprint for the labels:
private let allLabels = ["Street", "City", "State", "Country"]
private var labelFootprint: some View {
ZStack {
ForEach(allLabels, id: \.self) { label in
Text(LocalizedStringKey(label))
}
}
.hidden()
}
The visible labels can then be shown as an overlay over the footprint. For example:
LabeledContent {
TextField("Street", text: $street)
} label: {
labelFootprint.overlay(alignment: .leading) {
Text("Street")
}
}
