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

iOS Swift中向NSMutableArray添加数据时应用崩溃求助

嘿,我一眼就看到了两个导致崩溃的关键问题,咱们来逐个解决:

1. 致命的类型不匹配(崩溃直接原因)

先看你的CartDataModal代码:

class CartDataModal: NSObject {
    static let shared_Inst = CartDataModal()
    var cartArrayDict: [String:Any]!
}

你把cartArrayDict声明成了字典类型([String:Any]),但在addTapped方法里却调用了数组的insert(_:at:)方法——字典根本没有这个方法!再加上你用了隐式解包!,APP直接因为调用不存在的方法崩溃。

修复:把购物车改成正确的数组类型

修改CartDataModal,把cartArrayDict改成存储商品字典的数组,并且初始化空数组(彻底避免可选值问题):

class CartDataModal: NSObject {
    static let shared_Inst = CartDataModal()
    // 改成数组类型,存储单个商品的字典,默认是空数组
    var cartArrayDict: [[String:Any]] = []
}

2. 强制解包的潜在崩溃风险

你的代码里多处用了(indexPath?.row)!这种强制解包,比如:

var selectedDict = restMenu[(indexPath?.row)!]

如果indexPath是nil(比如cell被移出tableView时),强制解包会直接触发崩溃。

修复:用可选绑定安全处理可选值

修改addTapped方法,用guard let安全获取indexPath和数组元素:

func addTapped(cell: RestaurantItemViewCell) {
    // 安全获取cell对应的indexPath,获取失败直接返回
    guard let indexPath = self.restTableView.indexPath(for: cell) else {
        print("无法定位当前cell的位置")
        return
    }
    
    print("the indexPath is", indexPath.row)
    print("all obj is",restMenu)
    
    // 安全获取选中的商品字典,避免下标越界
    guard var selectedDict = restMenu[safe: indexPath.row] else {
        print("当前index超出菜单数组范围")
        return
    }
    
    print("selected dict is",selectedDict)
    selectedDict["ItemQuant"] = cell.itemQuantityLabel.text
    print("selected dict is",selectedDict)
    
    // 现在可以安全地添加到购物车了(类型匹配)
    // 购物车一般是追加商品,用append更合理;如果需要插入指定位置再用insert
    CartDataModal.shared_Inst.cartArrayDict.append(selectedDict)
    
    // 更新原菜单数组的逻辑可以保留,这里也没有强制解包了
    restMenu.remove(at: indexPath.row)
    restMenu.insert(selectedDict, at: indexPath.row)
    print("restmenu is",restMenu)
}

如果你的项目里没有数组的安全下标扩展,记得加上这个(非常实用):

extension Array {
    subscript(safe index: Index) -> Element? {
        // 先判断下标是否在数组范围内,再返回元素
        return indices.contains(index) ? self[index] : nil
    }
}

额外优化小建议

  • 尽量少用NSMutableArray,Swift原生的Array类型更安全、更易用,你从plist加载数据时可以直接用Swift数组,不用转成OC的可变数组。
  • 建议把购物车的操作封装成方法,比如在CartDataModal里加一个addItem(_ item: [String:Any]),这样代码更清晰,也方便后续扩展。
  • 长远来看,用自定义模型(比如struct MenuItem)代替[String:Any]字典,类型安全会帮你减少很多调试和崩溃的麻烦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:20:44