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
相关产品推荐
相关产品推荐

