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

删除UITableView最后一个Cell触发Invalid update错误求助

iOS UITableView滑动删除最后一个Cell报错的原因与修复方案

问题现象

滑动删除UITableView的Cell时多数场景功能正常,但删除最后一个Cell时会触发如下错误:

Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to...

错误原因

你的numberOfRowsInSection方法做了特殊处理:当resultArray为空时返回1(用来显示空状态提示Cell)。但删除最后一个元素后,你只更新了数据源,却没有正确同步UITableView的更新逻辑:

  1. 删除最后一个Cell前,resultArray.count为1,tableView显示1行;
  2. 删除元素后,resultArray变为空,此时numberOfRowsInSection应该返回1;
  3. 但SwipeCell的.destructive扩展样式默认会告诉tableView「删除1行,行数从1变为0」,这和你数据源返回的行数1产生冲突,触发了iOS的tableView更新校验错误。

修复方案

方案一:修改删除回调的tableView更新逻辑

在删除数据源后,根据数组是否为空选择不同的tableView更新方式:

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
    guard orientation == .right else { return nil }
    let deleteAction = SwipeAction(style: .destructive, title: "Delete") { action, indexPath in
        // 移除数据源元素
        self.resultArray.remove(at: indexPath.row)

        // 保存数据到本地
        let encoder = PropertyListEncoder()
        do {
            let data = try encoder.encode(self.resultArray)
            try data.write(to: self.filePath!)
        } catch {
            print("There was an error saving data: \(error)")
        }

        // 同步更新tableView
        if self.resultArray.isEmpty {
            // 数组为空时,直接刷新整个tableView,显示空状态Cell
            self.resultsTableView.reloadData()
        } else {
            // 数组还有元素时,删除指定行
            self.resultsTableView.deleteRows(at: [indexPath], with: .automatic)
        }
    }
    
    deleteAction.image = UIImage(named: "deleteIcon")
    return [deleteAction]
}

方案二:改用BackgroundView实现空状态(更推荐)

把空状态提示从Cell改为tableView的backgroundView,这样numberOfRowsInSection可以直接返回数据源长度,避免行数计算冲突:

  1. 修改numberOfRowsInSection方法:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return resultArray.count
}
  1. 添加空状态更新方法:
private func updateEmptyState() {
    if resultArray.isEmpty {
        // 创建空状态提示Label
        let emptyLabel = UILabel()
        emptyLabel.text = "No Saved Results Yet."
        emptyLabel.font = UIFont(name: "Caveat", size: 30.0)
        emptyLabel.textAlignment = .center
        emptyLabel.backgroundColor = blueCell
        // 设置为tableView的背景视图
        resultsTableView.backgroundView = emptyLabel
        resultsTableView.separatorStyle = .none
    } else {
        // 有数据时恢复默认背景和分隔线
        resultsTableView.backgroundView = nil
        resultsTableView.separatorStyle = .singleLine
    }
}
  1. 在数据更新的地方调用该方法:
  • 在loadCellName末尾添加:
resultArray = decodedData
updateEmptyState()
self.resultsTableView.reloadData()
  • 在删除回调中添加:
self.resultArray.remove(at: indexPath.row)
// 保存数据...
updateEmptyState()
self.resultsTableView.deleteRows(at: [indexPath], with: .automatic)

这种方式更符合UITableView的设计规范,也能彻底避免行数不匹配的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 07:40:31