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

Swift追加cellType后UITableView触发索引越界崩溃问题

问题原因

索引越界的核心问题有两个:

  • cellTypes更新逻辑错误:搜索返回新结果时,你直接用+=追加.location类型条目,没有清空上一次搜索生成的旧.location条目,多次搜索后cellTypes的长度会持续累加,和places数组的实际长度完全不匹配。
  • 取值逻辑没有适配多cell类型:列表里现在混排了.currentLocation、.location、.empty三种cell,你不管当前行是什么类型,直接用indexPath.row去places里取数据,只要存在非.location类型的cell,索引就会错位。之前尝试的indexPath.row +1/indexPath.row -1属于硬编码偏移,只要cell顺序、数量变了就会失效,根本解决不了问题。
修复步骤
  1. 修改搜索结果加载回调,每次拿到新的搜索结果时重新构建cellTypes数组,不要直接追加:
locationInteractor.didPlacesLoaded = { [weak self] places in
    DispatchQueue.main.async {
        guard let self = self else { return }
        self.places = places
        var newCellTypes: [CellType] = []
        // 固定优先展示当前位置(如果已加载完成)
        if self.currentLocation != nil {
            newCellTypes.append(.currentLocation)
        }
        // 再根据搜索结果追加对应类型
        if places.isEmpty {
            newCellTypes.append(.empty)
        } else {
            newCellTypes += Array(repeating: .location, count: places.count)
        }
        self.cellTypes = newCellTypes
        self.tableView.reloadData()
    }
}
  1. 修改当前位置加载回调,不要直接append.currentLocation,避免重复添加、顺序错乱:
locationInteractor.didCurrrentPlaceLoaded = { [weak self] currentPlace in
    guard let self = self else { return }
    self.currentLocation = currentPlace
    var newCellTypes: [CellType] = [.currentLocation]
    // 追加已有的其他类型cell,过滤掉重复的currentLocation
    newCellTypes.append(contentsOf: self.cellTypes.filter { $0 != .currentLocation })
    self.cellTypes = newCellTypes
    self.tableView.reloadData()
}
  1. 修改cell配置逻辑,先判断当前行的cell类型,计算正确的索引后再取数据,增加边界判断兜底:
private func locationTableViewCell(indexPath: IndexPath) -> PostSelectLocationTableViewCell {
    let locationCell = tableView.dequeueReusableCell(forIndexPath: indexPath) as PostSelectLocationTableViewCell
    let currentType = cellTypes[indexPath.row]
    switch currentType {
    case .currentLocation:
        if let currentPlace = currentLocation {
            locationCell.configure(model: currentPlace)
        }
    case .location:
        // 计算location类型在places数组中的真实索引:如果当前位置cell存在,索引偏移1位
        let offset = currentLocation != nil ? 1 : 0
        let placeIndex = indexPath.row - offset
        // 边界兜底,避免偶现越界
        guard placeIndex >= 0, placeIndex < places.count else { return locationCell }
        let place = places[placeIndex]
        locationCell.configure(model: place)
    case .empty:
        // 自行补充空态cell配置逻辑
        break
    }
    return locationCell
}
注意事项
  • 多类型cell的列表不要直接用append/+=更新类型数组而不做去重、重置处理,很容易出现条目重复、数量不匹配的问题
  • 永远不要直接拿indexPath.row作为多数据源混排列表的取值索引,必须根据当前行的类型计算对应数据源的偏移量,建议加边界判断做崩溃兜底

内容的提问来源于stack exchange,提问作者Mert Köksal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 03:57:37