You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI购物车优化:点击按钮更新商品数量而非重复添加

SwiftUI购物车重复添加与数量更新优化方案

核心思路

解决重复添加和数量更新的关键是通过商品唯一标识(如id)判断购物车中是否已存在该商品:存在则累加数量,不存在则新增商品记录。

实现步骤与代码示例

1. 定义商品模型

创建遵循Identifiable的商品模型,确保每个商品有唯一标识:

struct Product: Identifiable {
    let id: UUID // 可用商品SKU等业务唯一值替代UUID
    let name: String
    let price: Double
    var quantity: Int // 购物车中的数量
    
    init(id: UUID = UUID(), name: String, price: Double, quantity: Int = 1) {
        self.id = id
        self.name = name
        self.price = price
        self.quantity = quantity
    }
}

2. 购物车ViewModel(推荐,分离逻辑与视图)

用ViewModel封装购物车数据和操作逻辑,符合MVVM架构:

import SwiftUI

class CartViewModel: ObservableObject {
    @Published var cartItems: [Product] = []
    
    func addToCart(_ product: Product) {
        // 查找购物车中是否存在目标商品
        if let index = cartItems.firstIndex(where: { $0.id == product.id }) {
            // 存在则数量+1
            cartItems[index].quantity += 1
        } else {
            // 不存在则新增商品(默认数量为1)
            cartItems.append(product)
        }
    }
}

3. 视图层调用

在视图中注入ViewModel,绑定按钮动作:

struct ProductListView: View {
    // 示例商品列表
    let products: [Product] = [
        Product(name: "商品A", price: 99.9),
        Product(name: "商品B", price: 199.9),
        Product(name: "商品C", price: 299.9)
    ]
    
    @StateObject private var cartVM = CartViewModel()
    
    var body: some View {
        VStack {
            List(products) { product in
                HStack {
                    VStack(alignment: .leading) {
                        Text(product.name)
                            .font(.headline)
                        Text("¥\(product.price, specifier: "%.2f")")
                            .font(.subheadline)
                            .foregroundColor(.gray)
                    }
                    Spacer()
                    Button(action: {
                        cartVM.addToCart(product)
                    }) {
                        Text("加入购物车")
                            .padding(.horizontal, 16)
                            .padding(.vertical, 8)
                            .background(Color.blue)
                            .foregroundColor(.white)
                            .cornerRadius(8)
                    }
                }
            }
            
            // 购物车预览区域
            VStack(alignment: .leading) {
                Text("购物车")
                    .font(.title2)
                    .bold()
                ForEach(cartVM.cartItems) { item in
                    HStack {
                        Text(item.name)
                        Spacer()
                        Text("x\(item.quantity)")
                        Text("¥\(item.price * Double(item.quantity), specifier: "%.2f")")
                    }
                }
            }
            .padding()
        }
    }
}

关键逻辑说明

  • 唯一标识判断:通过firstIndex(where: { $0.id == product.id })精准定位购物车中的商品,避免重复添加。
  • 自动视图刷新:ViewModel中cartItems用@Published修饰,修改数量后视图会自动更新。
  • 逻辑分离:ViewModel封装购物车操作,后续扩展删除、清空等功能时无需改动视图代码。

无ViewModel简化方案

若不需要架构分层,直接在视图中用@State管理购物车数据:

struct ProductListView: View {
    let products: [Product] = [...]
    @State private var cartItems: [Product] = []
    
    func addToCart(_ product: Product) {
        if let index = cartItems.firstIndex(where: { $0.id == product.id }) {
            cartItems[index].quantity += 1
        } else {
            cartItems.append(product)
        }
    }
    
    // body部分同前,按钮action调用self.addToCart(product)
}

内容的提问来源于stack exchange,提问作者user21666271

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:52:20