I'm trying make it so that when the plus button is pushed in ListView the price will increment by one and be reflected on the screen. I'm not getting any errors, and I'm getting the expected result from the print statement, but the view will not update. I've tried just incrementing the price directly in the button as opposed to creating a variable for the same thing. but I get an error saying the left side is immutable because it's a let constant. Any help would be appreciated, I'm getting really frustrated. Thank you!
struct Product: Identifiable { let id = UUID() var name: String var price: Double var aisle: Int var location: Int }
class Inventory { var inventory: [Product] = [ Product(name: "Coke", price: 2.99, aisle: 1, location: 10), Product(name: "Pepsi", price: 3.99, aisle: 1, location: 6), Product(name: "Dr. Pepper", price: 1.99, aisle: 2, location: 8), Product(name: "Pibb", price: 1.50, aisle: 2, location: 1) ] }
struct ListView: View { @State var base = Inventory().inventory
@State var userList: [Product] = []
var body: some View {
List {
ForEach(base) { product in
var thing = product.price
HStack {
Text(product.name)
Spacer()
Button {
thing += 1
print(thing)
} label: {
Image(systemName: "plus")
}
Text("\(thing, specifier: "%.2f")")
}
}
}
}
}
struct ListView_Previews: PreviewProvider { static var previews: some View { ListView() } }
Welcome to the forum.
You should first format code with code formatter tool. More readable.
struct Product: Identifiable {
let id = UUID()
var name: String
var price: Double
var aisle: Int
var location: Int
}
class Inventory {
var inventory: [Product] = [ Product(name: "Coke", price: 2.99, aisle: 1, location: 10), Product(name: "Pepsi", price: 3.99, aisle: 1, location: 6), Product(name: "Dr. Pepper", price: 1.99, aisle: 2, location: 8), Product(name: "Pibb", price: 1.50, aisle: 2, location: 1) ]
}
struct ListView: View {
@State var base = Inventory().inventory
@State var userList: [Product] = []
var body: some View {
List {
ForEach(base) { product in
var thing = product.price
HStack {
Text(product.name)
Spacer()
Button {
thing += 1
print(thing)
} label: {
Image(systemName: "plus")
}
Text("\(thing, specifier: "%.2f")")
}
}
}
}
}
struct ListView_Previews: PreviewProvider {
static var previews: some View {
ListView()
}
}
You are missing essential elements of SwiftUI.
- you create a local var (thing), so the change remains local, it is not propagated to update Text().
- you have to use a State var.
- Your tried using base, but base in ForEach is a local constant, it cannot be updated
- You have to update directly the base state var, at the right index
- To do so, a simple way is to use enumerated.
Here is a code that works:
struct Product: Identifiable, Hashable { // Need to make it Hashable
let id = UUID()
var name: String
var price: Double
var aisle: Int
var location: Int
}
class Inventory {
var inventory: [Product] = [ Product(name: "Coke", price: 2.99, aisle: 1, location: 10), Product(name: "Pepsi", price: 3.99, aisle: 1, location: 6), Product(name: "Dr. Pepper", price: 1.99, aisle: 2, location: 8), Product(name: "Pibb", price: 1.50, aisle: 2, location: 1) ]
}
struct ListView: View {
@State var base = Inventory().inventory
@State var userList: [Product] = []
var body: some View {
List {
ForEach(Array(base.enumerated()), id: \.element) { index, product in // index to access directly base[index] ; it is equal to product, but this is modifiable
// ForEach(base) { product in
// var thing = product.price
HStack {
Text(product.name)
Spacer()
Button {
base[index].price += 1 // thing += 1
} label: {
Image(systemName: "plus")
}
Text("\(product.price, specifier: "%.2f")") // Text("\(thing, specifier: "%.2f")")
}
}
}
}
}
If that works, don't forget to close the thread by marking this answer as correct. Otherwise, explain what is the remaining issue.
Note: if you find enumerated too complex, you could add an index to Product, which will be its rank in the array (starting at 0). And use it to access the right element in base
struct Product: Identifiable {
let id = UUID()
var name: String
var price: Double
var aisle: Int
var location: Int
var index: Int = 0
}
class Inventory {
var inventory: [Product] = [
Product(name: "Coke", price: 2.99, aisle: 1, location: 10, index: 0),
Product(name: "Pepsi", price: 3.99, aisle: 1, location: 6, index: 1),
Product(name: "Dr. Pepper", price: 1.99, aisle: 2, location: 8, index: 2),
Product(name: "Pibb", price: 1.50, aisle: 2, location: 1, index: 3)
]
}
List {
ForEach(base) { product in
HStack {
Text(product.name)
Spacer()
Button {
base[product.index].price += 1
} label: {
Image(systemName: "plus")
}
Text("\(product.price, specifier: "%.2f")")
}
}
Good continuation.