Swift UI View return error mutating state error with ForEach Operator

68 views Asked by At

I am using ForEach loop to display the data into view . ForEach return immutable state but now I have to update the view properties like updating the shopping cart quantity. This is an shopping cart view where I am using stepper update the view like increasing and decreasing the item form view . But I have the error is Left side of mutating operator isn't mutable: 'item' is a 'let' constant I got the reason it happening because of ForEach . What is the alternative to correct this error.

Error on this line ..

Stepper {
             Text("\(Image(systemName: "multiply"))\(item.quantity)")
               }
                 onIncrement: {
                     item.quantity += 1 // error on this line 

                           }
                          onDecrement: {
                              if item.quantity > 1 {
                                        item.quantity -= 1
                                    }
                                }

Here is my json.

import Foundation

// MARK: - Welcome
struct ProductData: Codable, Hashable {
    let carts: [Cart]
}

// MARK: - Cart
struct Cart: Codable, Hashable {
    let id: Int
    let products: [Product]
}

// MARK: - Product
struct Product: Codable, Hashable, Identifiable {
    let id: Int
    let title: String
    var price, quantity, total: Int
    let discountPercentage: Double
    let discountedPrice: Int
    let thumbnail: String
}

Here is the order class ..

import SwiftUI

class Order: ObservableObject {

    @Published var products = [Product]()
    @Published private(set) var productTotal: Int = 0

    func add(item: Product) {
       if let index = products.firstIndex(where: {$0.id == item.id }) {
           products[index].quantity += 1
       } else {
           products.append(item)
       }
    }
   }

Here is the Order view ..

import SwiftUI

struct OrderView: View {
    @EnvironmentObject var order: Order

    var body: some View {
        NavigationStack {
            List {
                Section {
                    ForEach(order.products) { item in
                        Section {
                            HStack {
                                Text("Description")
                                    .foregroundColor(.blue)
                                    .bold()
                                Spacer()
                                Text("Action")
                                    .foregroundColor(.blue)
                                    .bold()
                            }
                        }

                        HStack {
                            if let url = URL(string: item.thumbnail) {
                                ProductAsyncImageView(url: url)
                                    .frame(width: 90, height: 90)
                                    .padding(.bottom, -10)
                                    .clipShape(Circle())
                            }
                            Spacer()

                            VStack {
                                HStack {
                                    Stepper {
                                        Text("\(Image(systemName: "multiply"))\(item.quantity)")

                                    }
                                onIncrement: {
                                    item.quantity += 1

                                }
                                onDecrement: {
                                    if item.quantity > 1 {
                                        item.quantity -= 1
                                    }
                                }

                                    Image(systemName: "trash")
                                        .foregroundColor(Color(hue: 1.0, saturation: 0.89, brightness: 0.835))
                                        .onTapGesture {
                                            order.remove(item: item)
                                        }
                                }
                            }
                            Spacer()
                        }

                        VStack {
                            HStack(spacing: 20) {
                                Text("Name: \(item.title)")
                                    .font(.subheadline)
                                    .frame(maxWidth: .infinity, alignment: .leading)
                                    .bold()

                            }
                            HStack {
                                Text("Price: £\(item.price)")
                                    .font(.subheadline)
                                    .bold()
                                    .frame(maxWidth: .infinity, alignment: .leading)
                                Text("Sub Total: £\(item.quantity * item.price)")
                                    .font(.subheadline)
                                    .bold()
                                    .frame(maxWidth: .infinity, alignment: .leading)
                            }
                        }
                    }
                }
                Section {
                    NavigationLink("Place Order") {
                    }
                }
            }
            .navigationTitle("Order")
        }
    }
}

Here is the screenshot error ..

enter image description here

0

There are 0 answers