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 ..