Swift可变状态报错:'quantity'为let常量无法修改
问题解决:修改购物车商品数量时报错的处理
错误原因分析
- 结构体属性不可变:原
Product结构体中所有属性用let声明,属于常量,无法修改。 - 值类型副本问题:
forEach循环中遍历的product是结构体的值副本,修改副本不会影响原数组中的元素,同时因为原属性是let,所以触发报错。
具体修改步骤
1. 修改Product结构体属性为可变
将Product中所有需要修改的属性从let改为var:
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 { var id: Int var title: String var price, quantity, total: Int var discountPercentage: Double var discountedPrice: Int var thumbnail: String }
2. 重写add函数,直接修改原数组元素
放弃forEach循环,改用firstIndex找到目标元素的索引,直接修改原数组中的元素(同时同步更新total和discountedPrice保证数据一致性):
class Order: ObservableObject { @Published var product = [Product]() @Published private(set) var productTotal: Int = 0 func add(item: Product) { if let index = product.firstIndex(where: { $0.id == item.id }) { // 找到已有商品,增加数量 product[index].quantity += 1 // 同步更新total和折扣后价格 product[index].total = product[index].price * product[index].quantity let discountAmount = Double(product[index].total) * product[index].discountPercentage / 100 product[index].discountedPrice = product[index].total - Int(discountAmount) } else { // 商品不存在,添加新商品(可根据需求调整初始数量) var newItem = item newItem.quantity = 1 newItem.total = newItem.price * newItem.quantity let discountAmount = Double(newItem.total) * newItem.discountPercentage / 100 newItem.discountedPrice = newItem.total - Int(discountAmount) product.append(newItem) } // 更新购物车总金额 productTotal = product.reduce(0) { $0 + $1.discountedPrice } } }
关键说明
- 结构体是值类型,遍历过程中得到的是元素副本,必须通过索引直接操作原数组才能生效。
mutating关键字仅适用于结构体的方法,Order是类,不需要添加该关键字。- 同步更新
total和discountedPrice是为了保证数据一致性,避免出现数量和金额不匹配的情况。
内容的提问来源于stack exchange,提问作者user21666271
相关产品推荐
相关产品推荐

