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

iOS MVVM架构下,食品列表添加商品后直接进购物车不显示的问题求助

问题分析&解决方案

我来帮你捋捋这个问题哈~你现在遇到的核心问题是:购物车的数据没有被持久化或全局共享。每次从食品列表跳转购物车时,你新建了ChartDataSourceModel和ChartViewModel实例,添加的商品只存在这个临时实例里;但直接进入购物车页面时,又会创建全新的实例,自然看不到之前添加的商品。

下面给你分步解决这个问题:


第一步:把购物车数据源改成全局共享的单例

首先要让所有页面使用同一个购物车数据源,这样不管从哪里添加商品,数据都能统一维护。

修改ChartDataSourceModel为单例

class ChartDataSourceModel {
    // 全局唯一实例
    static let shared = ChartDataSourceModel()
    // 初始化空数组,避免可选值带来的崩溃风险
    var dataListArray: [CartModel] = []
    
    // 私有构造方法,确保只能通过shared获取实例
    private init() {}
}

调整ChartViewModel的初始化逻辑

让ViewModel默认使用共享的数据源,不用每次手动创建:

class ChartViewModel {
    let datasourceModel: ChartDataSourceModel
    var insertedArray: CartModel?
    
    // 默认使用全局共享的数据源,也支持传入自定义数据源(方便测试)
    init(withdatasource datasource: ChartDataSourceModel = .shared) {
        self.datasourceModel = datasource
    }
    
    func add() {
        guard let item = insertedArray else { return }
        datasourceModel.dataListArray.append(item)
        print("当前购物车商品:\(datasourceModel.dataListArray)")
        print("新增商品名称:\(item.offerdetailAddName)")
        // 发送通知,告诉购物车页面数据更新了
        NotificationCenter.default.post(name: NSNotification.Name("CartDataUpdated"), object: nil)
    }
}

优化FoodListViewController的按钮点击逻辑

不用再手动创建ChartDataSourceModel,直接用共享实例:

cell.cartaddCell = {[weak self] in 
    guard let self = self, let indexPath = self.tableView.indexPath(for: $0) else { return }
    // 创建要添加的购物车商品模型
    let cartmodel = CartModel(withoffermodel: self.offerViewModel.datafordisplay(atindex: indexPath))
    // 直接初始化ViewModel,默认用共享数据源
    let cartViewModel = ChartViewModel()
    cartViewModel.insertedArray = cartmodel
    cartViewModel.add()
    // 跳转购物车页面
    let cartViewController = ChartViewController(nibName: "ChartViewController", bundle: nil, withViewModel: cartViewModel)
    self.navigationController?.pushViewController(cartViewController, animated: true)
}

第二步:让购物车页面能自动刷新数据

直接进入购物车页面时,要确保能加载共享数据源里的已有数据,并且当数据变化时自动刷新:

修改ChartViewController的代码

class ChartViewController: UIViewController {
    var viewModel: ChartViewModel!
    @IBOutlet weak var tableView: UITableView!
    
    init(nibName: String?, bundle: Bundle?, withViewModel vm: ChartViewModel) {
        self.viewModel = vm
        super.init(nibName: nibName, bundle: bundle)
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 页面加载时先刷新一次数据
        tableView.reloadData()
        // 监听购物车数据更新的通知
        NotificationCenter.default.addObserver(
            self, 
            selector: #selector(refreshCartData), 
            name: NSNotification.Name("CartDataUpdated"), 
            object: nil
        )
    }
    
    @objc private func refreshCartData() {
        tableView.reloadData()
    }
    
    // 页面销毁时移除通知监听,避免内存泄漏
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    
    // MARK: - TableView数据源方法
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return viewModel.datasourceModel.dataListArray.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CartCell", for: indexPath)
        let item = viewModel.datasourceModel.dataListArray[indexPath.row]
        cell.textLabel?.text = item.offerdetailAddName
        return cell
    }
}

第三步(可选):添加持久化,APP重启后数据不丢失

如果希望关闭APP再打开,购物车数据还在,可以给ChartDataSourceModel加上本地持久化逻辑(用UserDefaults简单实现,复杂场景可以用Core Data):

让CartModel遵循Codable协议

struct CartModel: Codable {
    var offerdetailAddName: String
    // 你的其他属性...
    
    init(withoffermodel model: OfferModel) {
        // 按照你的原有逻辑初始化属性
        self.offerdetailAddName = model.name // 假设OfferModel有name属性
    }
}

给ChartDataSourceModel添加持久化方法

class ChartDataSourceModel {
    static let shared = ChartDataSourceModel()
    var dataListArray: [CartModel] = []
    private let userDefaultsKey = "CartData"
    
    private init() {
        // 初始化时从UserDefaults加载数据
        loadDataFromLocal()
    }
    
    // 从本地加载数据
    private func loadDataFromLocal() {
        guard let data = UserDefaults.standard.data(forKey: userDefaultsKey) else { return }
        do {
            dataListArray = try JSONDecoder().decode([CartModel].self, from: data)
        } catch {
            print("加载购物车数据失败:\(error)")
        }
    }
    
    // 保存数据到本地
    private func saveDataToLocal() {
        do {
            let data = try JSONEncoder().encode(dataListArray)
            UserDefaults.standard.set(data, forKey: userDefaultsKey)
        } catch {
            print("保存购物车数据失败:\(error)")
        }
    }
    
    // 对外提供添加商品的方法,自动保存
    func addItem(_ item: CartModel) {
        dataListArray.append(item)
        saveDataToLocal()
    }
}

调整ChartViewModel的add方法

func add() {
    guard let item = insertedArray else { return }
    datasourceModel.addItem(item)
    NotificationCenter.default.post(name: NSNotification.Name("CartDataUpdated"), object: nil)
}

这样修改后,不管是从食品列表跳转购物车,还是直接进入购物车页面,都能看到所有已添加的商品;甚至APP重启后,购物车数据也不会丢失啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:35:52