Reputation: 2000
Today I have a problem on SwiftUI
in a ForEach
.
I have a several list of products from different stores, the thing is I need to modify Stock when I press one of the buttons to increase or decrease it. but when I really try to make this I have the following error:
Left side of mutating operator isn't mutable: 'product' is a 'let' constant SwiftUI
I don't know how to make it works and I'm here to hear some suggestions
@State var shoppingCartList : [Product]
ForEach(productsByStore(storeId: store.id), id: \.self){product in
VStack(alignment: .leading, spacing: 0){
HStack{
Group{
HStack{
HStack{
Button(action: {
if (product.quantity > 1){ // error here: product.quantity -= 1
}
}){
Text("—")
.multilineTextAlignment(.center)
}
.padding([.leading], 5)
Text(String(product.quantity))
Button(action: {
if product.quantity < product.stock!{
// error here: product.quantity += 1
}
}){
Text("+")
.multilineTextAlignment(.center)
}
}
Spacer()
Text("available: " + String(describing: product.stock!))
}
}
}
}
Divider()
}
Spacer()
}
func productsByStore(storeId: Int) ->[Product] {
return shoppingCartList.filter{$0.storeId == storeId}
}
PS. productsByStore()
returns a list of products according to the store
PS2. product.stock is the number of available items on stock and product.quantity is the number of items that user can select.
ex: Palm One -> Quantity = 4. Stock = 10
I could add or remove the number of palm ones using buttons (+ and -)
PS3. Product Struct
struct Product: Hashable, Codable{
var name: String
var quantity: Int
var stock: Int?
var storeId: Int
init(from decoder: Decoder) throws{
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decodeIfPresent(String.self, forKey: .name) ?? ""
quantity = try container.decodeIfPresent(Int.self, forKey: .quantity) ?? 0
stock = try container.decodeIfPresent(Int?.self, forKey: .stock) ?? 0
storeId = try container.decodeIfPresent(Int.self, forKey: .storeId) ?? 0
}
private enum CodingKeys: String, CodingKey{
case name = "Nombre"
case quantity = "Cantidad"
case stock = "Stock"
case storeId = "IdStore"
}
init(name: String, quantity: Int, stock: Int?, storeId: Int ){
self.name = name
self.quantity = quantity
self.stock = stock
self.storeId = storeId
}
}
Upvotes: 0
Views: 136
Reputation: 2000
I solved like this:
@State var selectedStock: Int = 0
Button(action: {
self.selectedStock = product.quantity
if self.selectedStock > 1 {
selectedStock -= 1
if let listIndex = shoppingCartList.firstIndex(where: {
$0 == currentProduct
}) {
var newProduct = product
newProduct.quantity = selectedStock
shoppingCartList[listIndex] = newProduct
}
}
}) {
Text("—")
}
Button(action: {
self.selectedStock = product.quantity
if self.selectedStock < product.stock!{
selectedStock += 1
if let listIndex = shoppingCartList.firstIndex(where: {
$0 == currentProduct
}) {
var newProduct = product
newProduct.quantity = selectedStock
shoppingCartList[listIndex] = newProduct
}
}
}) {
Text("+")
}
Upvotes: 1