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

Swift委托函数中获取选中TableView Cell所在Section的方法

解决TableView Cell按钮点击时获取Section的问题

问题根源

你遇到的崩溃本质是:不同分组(Section)里的单元格(Cell)可能有相同的indexPath.row值,只传递row的话,控制器无法区分当前点击的Cell属于哪个Section,导致访问subCategoryModel时取到了错误的索引,进而触发数组越界崩溃。

具体解决方案

我们只需要修改委托逻辑,让它同时传递Section和Row的信息,就能精确定位点击位置。下面是分步修改方案:


1. 更新委托协议

把原来只传row的协议,改成传递完整的IndexPath(它本身就包含section和row,是最灵活的方式):

protocol ResMenuDetailDelegate { 
    func addOnBtnTapped(at indexPath: IndexPath) 
}

2. 修改Cell的按钮点击逻辑

这里提供两种可靠的方式获取当前Cell的IndexPath:

方式一:直接从TableView获取(推荐)
不需要额外存储数据,通过Cell的父视图找到对应的TableView,再拿到索引:

var delegate: ResMenuDetailDelegate?

@IBAction func addBtnTapped(_ sender: Any) {
    // 找到当前Cell所属的TableView,再获取对应的IndexPath
    guard let tableView = self.superview as? UITableView,
          let indexPath = tableView.indexPath(for: self) else {
        return
    }
    delegate?.addOnBtnTapped(at: indexPath)
}

方式二:配置Cell时存储IndexPath
在Cell类里新增一个属性,专门存当前Cell的索引:

var delegate: ResMenuDetailDelegate?
var indexPath: IndexPath? // 新增存储索引的属性

@IBAction func addBtnTapped(_ sender: Any) {
    guard let indexPath = indexPath else { return }
    delegate?.addOnBtnTapped(at: indexPath)
}

3. 调整TableView的cellForRow方法

  • 如果用方式一:直接删掉cell.addBtn.tag = indexPath.row这行代码(tag已经没用了)。
  • 如果用方式二:在配置Cell时给indexPath属性赋值:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if tableView == resMenuTableView{
        let cell = resMenuTableView.dequeueReusableCell(withIdentifier: "detailMenuCell", for: indexPath) as! RestaurantMenuDetailTVC
        // 先把当前要展示的item取出来,避免重复写长索引
        let currentItem = subCategoryModel![indexPath.section].items[indexPath.row]
        
        cell.dishTitleLbl.text = currentItem.itemName
        cell.descriptionLbl.text = currentItem.itemDescription
        cell.priceLbl.text = String(currentItem.itemPrice)
        
        // 方式一:不需要设置tag,删除这行
        // cell.addBtn.tag = indexPath.row
        // 方式二:给Cell的indexPath属性赋值
        // cell.indexPath = indexPath
        
        cell.delegate = self
        cell.selectionStyle = .none
        cell.backgroundColor = UIColor.clear
        return cell
    }
    // 记得处理其他TableView的情况,返回默认Cell
    return UITableViewCell()
}

4. 更新控制器的委托实现

现在可以通过indexPath精准拿到section和row,再也不会取错数据了:

extension RestaurantMenuDetailVC : ResMenuDetailDelegate{
    func addOnBtnTapped(at indexPath: IndexPath) {
        print("点击了Section: \(indexPath.section), Row: \(indexPath.row)")
        let currentItem = subCategoryModel![indexPath.section].items[indexPath.row]
        let addonCategory = currentItem.addonCategory
        print(addonCategory as Any)
        
        // 接下来就可以把addonCategory传给弹窗的TableView了
    }
}

额外提醒

尽量不要用tag传递多维度的位置信息,因为tag是单一Int值,无法同时存储section和row,不同section的row很容易重复,会埋下崩溃隐患。直接传递IndexPath是iOS开发中定位TableView Cell位置的标准做法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:57:02