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

