UITableViewCell删除行触发数组越界且列表不更新问题排查
问题分析与修复方案
核心问题
- 数据源不同步:删除
scheduler中的元素后,未同步更新scheduleArray,导致tableView的行数计算(numberOfRowsInSection)仍基于旧的scheduleArray长度,但实际scheduler中的数组已缩短,最终触发数组越界。 cellForRowAt中的不当操作:每次创建cell时都重新给scheduleArray赋值,且使用强制解包(scheduler![self.day])增加崩溃风险;同时存在不必要的DispatchQueue.main.async冗余代码。
具体修复步骤
1. 同步删除后的数据源
在删除成功的Alert回调中,删除scheduler元素后需同步更新scheduleArray,确保tableView的数据源统一:
deleteAlert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action: UIAlertAction!) in guard var daySchedule = self.scheduler?[self.day] else { return } // 确保索引合法,避免越界 if tag < daySchedule.count { daySchedule.remove(at: tag) self.scheduler?[self.day] = daySchedule // 同步更新用于tableView展示的数据源 self.scheduleArray = daySchedule self.scheduleView.reloadData() } }))
2. 优化cellForRowAt方法
- 移除重复的
scheduleArray赋值操作,避免每次创建cell都覆盖数据源 - 替换强制解包为可选绑定,降低崩溃风险
- 删除冗余的
DispatchQueue.main.async(cellForRowAt本身在主线程执行)
修改后的cellForRowAt:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = Bundle.main.loadNibNamed("schedulerCell", owner: self, options: nil)?.first as! scheduleCell cell.cellDelegate = self cell.editBtn.tag = indexPath.row cell.deleteSchedule.tag = indexPath.row // 安全获取当前行数据,处理数据不完整的情况 guard let currentSchedule = self.scheduleArray?[indexPath.row], currentSchedule.count >= 2 else { cell.timeLabel1.text = "" cell.timeLabel2.text = "" return cell } cell.timeLabel1.text = currentSchedule[0] cell.timeLabel2.text = currentSchedule[1] return cell }
3. 移除不必要的强制解包
在getData等方法中,用可选绑定替代强制解包,提升代码安全性:
func getData(){ guard let getUrl = ScheduleURL?["GET"] else { print("GET 请求URL未配置") return } AFFunctions.getAFRequest(ofType: ScheduleResponse.self, url: getUrl) { responseData, statusCode in print(responseData?.data?.scheduler, statusCode) self.scheduler = responseData?.data?.scheduler DispatchQueue.main.async { // 初始化默认显示周日的日程 self.showDetail(day: "Sunday", dayNum: 0) } } }
额外建议
- 给
scheduleArray和scheduler设置初始空值,减少可选类型的处理成本:var scheduleArray: [[String]] = [] var scheduler: [String: [[String]]] = [:] - 用数组映射简化
daySelected中的日期匹配逻辑:let days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] self.dayNum = sender.tag self.day = days[min(sender.tag, days.count - 1)]
内容的提问来源于stack exchange,提问作者AbheshekSharma
相关产品推荐
相关产品推荐

