I want to add a row number to a race list as shown above. Currently everyone is coming first. It's conditional as some people didn't finish (DNF).
So first I set up an ObservableObject:
class GlobalSettings: ObservableObject {
@Published var counter: Int = 0
}
The structure that display each row is called from:
Section {
List {
ForEach(entrants) { entrant in
ResultsCell(entrant: entrant)
}
}
}
The row is displayed by ResultsCell:
struct ResultsCell: View {
let entrant: EntrantsDatabase1
@EnvironmentObject var globalSettings: GlobalSettings
var body: some View {
HStack {
Spacer()
.frame(width: 5)
if entrant.dateTime != 999.999 {
globalSettings.counter += 1
Text("\(globalSettings.counter).")
// Text("1.")
.frame(width: 20, height: 40, alignment: .leading)
.bold()
} else {
Text("-")
.frame(width: 20, height: 40, alignment: .leading)
.bold()
}
Spacer()
.frame(width: 5)
CircledText(text: String(entrant.number))
.frame(width: 48, height: 40, alignment: .leading)
.bold()
Spacer()
.frame(width: 10)
Text(entrant.name)
.frame(width: 160, height: 40, alignment: .leading)
.bold()
Spacer()
.frame(width: 10)
if entrant.dateTime != 999.999 {
Text("\(entrant.dateTime, specifier: "%.3f")")
.frame(width: 70, height: 40, alignment: .trailing)
.bold()
} else {
Text("DNF")
.frame(width: 70, height: 40, alignment: .trailing)
.bold()
}
}
.listRowBackground(entrant.dateTime == 999.999 ? Color.red: Color(.tertiarySystemBackground))
}
}
The row counter only increments if the person finishes. Using this approach I get a
'buildExpression' is unavailable: this expression does not conform to 'View'
error when I try and use the globalSettings.counter variable.
Is this approach valid/Workable?
You don't need the GlobalSettings
.
Try this approach using
ForEach(Array(entrants.enumerated()),...
as shown in the example code
Note, comparing two Doubles
in your
if entrant.dateTime != 999.999
etc... can lead to problems due to floating-point errors.
struct ContentView: View {
// for testing
let entrants = [
EntrantsDatabase(id: 1, number: "1", dateTime: 1.3, name: "entrant-1"),
EntrantsDatabase(id: 2, number: "2", dateTime: 45.6, name: "entrant-2"),
EntrantsDatabase(id: 3, number: "3", dateTime: 999.999, name: "entrant-3")
]
var body: some View {
VStack {
Section {
List {
ForEach(Array(entrants.enumerated()), id: \.1.id) { index, entrant in // <--- here
ResultsCell(index: index, entrant: entrant) // <--- here
}
}
}
}
.padding()
}
}
// for testing
struct EntrantsDatabase: Identifiable {
var id: Int // <--- important
var number: String
var dateTime: Double
var name: String
}
struct ResultsCell: View {
let index: Int // <--- here
let entrant: EntrantsDatabase
var body: some View {
HStack {
Spacer()
.frame(width: 5)
if entrant.dateTime != 999.999 {
Text("\(index).").foregroundStyle(.blue) // <--- here
.frame(width: 20, height: 40, alignment: .leading)
.bold()
} else {
Text("-")
.frame(width: 20, height: 40, alignment: .leading)
.bold()
}
Spacer()
.frame(width: 5)
// CircledText(text: String(entrant.number))
Text(String(entrant.number)) // <--- for my testing
.frame(width: 48, height: 40, alignment: .leading)
.bold()
Spacer()
.frame(width: 10)
Text(entrant.name)
.frame(width: 160, height: 40, alignment: .leading)
.bold()
Spacer()
.frame(width: 10)
if entrant.dateTime != 999.999 {
Text("\(entrant.dateTime, specifier: "%.3f")")
.frame(width: 70, height: 40, alignment: .trailing)
.bold()
} else {
Text("DNF")
.frame(width: 70, height: 40, alignment: .trailing)
.bold()
}
}
.listRowBackground(entrant.dateTime == 999.999 ? Color.red: Color(.tertiarySystemBackground))
}
}