I'm trying to create a new instance of my class "people" and add it to my list called listOfPeople. At the start, I ask how many people am I going to add. After I answer that, I add 1 to the variable "level" so I can continue as if it where a for loop. Now at level 1, I add the name and numberAssigned to the new instance which would supposedly go in listOfPeople in the position in which the variable counter is on. After I click the button with text "Add name" I would add another name and so on until I reach the numberOfpeople, so again, trying to simulate a for loop (I'm aware I have not added the logic for the textfield and button to add a new instance and stop when counter reaches the numberOfpeople). However, in this case, after I add the persons name and numberAssigned, it gives me the error in image number three. Which says "Thread 1: Fatal error: Index out of range."
How could I make this work? I learned how to do this in c++ but I clearly do not know how to accomplish it in swiftui. Any help is appreciated! ;)
I could make it work this way, the only problem is that if the user wants to add 1,000 people, I would have to have 1,000 variables pre-created, which I do not want, I want to be able to do it as a for-loop per se.
Please, when you post code, post the code as text not images. And use code formatter tool.
struct ContentView: View {
class People { // Uppercase name
var name = ""
var numberAsigned = 0
}
@State var level = 0
@State var numberOfpeople = 0
@State var name = ""
@State var counter = 0
@State var assigned = 0
/*
var person1 = people()
var person2 = people()
var person3 = people()
var person4 = people()
var person5 = people()
var person6 = people()
*/
var body: some View {
var listOfPeople: [People] = []
if level == 0 {
VStack {
TextField("How many people", value: $numberOfpeople, format: .number)
.frame (width: 100, height: 100)
ZStack {
Rectangle()
.frame (width: 100, height: 100)
.cornerRadius(25)
Button(action: { level += 1 },
label: { Text("Add")
.foregroundColor(Color.white)
})
}
}
} else if level == 1 {
VStack {
TextField ("Name of person", text: $name)
TextField( "Number assigned", value: $assigned, format: .number)
Button(action: {
listOfPeople[counter].name = name
listOfPeople[counter].numberAsigned = assigned
counter += 1
}, label: {
Text ("Add Name")
})
}
}
}
}
Note also that class names should start with Uppercase (People)
You never append People to listOfPeople, which is declared as:
var listOfPeople: [People] = []
Hence it is always empty and crashes when you try to access an element.
Then, listOfPeople should be a State var, otherwise it is reinitialized each time you redraw the view.
This works better:
struct ContentView: View {
class People { // Uppercase name
var name = ""
var numberAsigned = 0 / probably a typo: numberAssigned
}
@State var level = 0
@State var numberOfpeople = 0
@State var name = ""
@State var counter = 0
@State var assigned = 0
@State var listOfPeople: [People] = []
var body: some View {
if level == 0 {
VStack {
TextField("How many people", value: $numberOfpeople, format: .number)
.frame (width: 300, height: 100)
ZStack {
Rectangle()
.frame (width: 100, height: 100)
.cornerRadius(25)
Button(action: { level += 1
for _ in 0..<numberOfpeople {
listOfPeople.append(People())
}
},
label: { Text("Add")
.foregroundColor(Color.white)
})
}
}
} else if level == 1 {
VStack {
TextField ("Name of person", text: $name)
TextField( "Number assigned", value: $assigned, format: .number)
Button(action: {
listOfPeople[counter].name = name
listOfPeople[counter].numberAsigned = assigned
counter += 1
}, label: {
Text ("Add Name")
})
}
}
}
}
Now you have to make your code more robust (disable button when completed), improve readability with labels for TextFields…
struct ContentView: View {
class People { // Uppercase name
var name = ""
var numberAsigned = 0
}
@State var level = 0
@State var numberOfpeople = 0
@State var name = ""
@State var counter = 0
@State var assigned = 0
@State var listOfPeople: [People] = []
var body: some View {
if level == 0 {
VStack {
HStack {
Text("How many people")
.frame (width: 150, height: 20, alignment: .trailing)
TextField("", value: $numberOfpeople, format: .number)
.frame (width: 50, height: 20, alignment: .leading)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
ZStack {
Rectangle()
.frame(width: 100, height: 100)
.cornerRadius(25)
Button(action: { level += 1
for _ in 0..<numberOfpeople {
listOfPeople.append(People())
}
},
label: { Text("Add")
.foregroundColor(Color.white)
})
}
}
} else if level == 1 {
VStack {
HStack {
Text("Name of person")
.frame (width: 150, height: 20, alignment: .trailing)
TextField ("", text: $name)
.frame (width: 150, height: 20, alignment: .leading)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
HStack {
Text("Number assigned")
.frame (width: 150, height: 20, alignment: .trailing)
TextField( "", value: $assigned, format: .number)
.frame (width: 150, height: 20, alignment: .leading)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
Button(action: {
listOfPeople[counter].name = name
listOfPeople[counter].numberAsigned = assigned
counter += 1
name = "" // Let us clear the name
}, label: {
Text ("Add Name")
})
.disabled(counter >= numberOfpeople)
}
}
}
}