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

Swift中调用scrollToRow偶现Last Exception Backtrace(0)错误如何解决?

如何预防UITableView scrollToRow时的Last Exception Backtrace(0)错误

这个错误大概率是异步执行时UI/数据源状态不一致导致的——比如异步块触发时,TableView已被销毁、数据源已更新,或是计算出的IndexPath本身非法。以下是针对性的预防方案:

1. 先校验控制器与TableView的存活状态

异步块执行时,当前控制器可能已经被释放,直接调用scrollToRow会触发野指针类错误。通过弱引用+状态检查提前拦截:

DispatchQueue.main.async { [weak self] in
    guard let self = self else { return }
    // 确认TableView仍处于活跃状态(假设你的TableView属性名为tableView)
    guard self.tableView.window != nil else { return }
    
    let section = self.numberOfSections - 1
    // 先判断section是否合法,避免出现负数
    guard section >= 0 else { return }
    let row = self.numberOfRows(inSection: section) - 1
    // 再判断row是否合法
    guard row >= 0 else { return }
    
    let indexPath = IndexPath(row: row, section: section)
    if self.hasRowAtIndexPath(indexPath: indexPath) {
        self.scrollToRow(at: indexPath, at: .bottom, animated: isAnimated)
    }
}

2. 修复IndexPath合法性校验逻辑

原代码直接用numberOfSections-1,如果numberOfSections为0会得到负数section,本身就是非法的。同时要确保hasRowAtIndexPath的实现严谨:

func hasRowAtIndexPath(indexPath: IndexPath) -> Bool {
    guard indexPath.section >= 0, indexPath.section < numberOfSections else { return false }
    guard indexPath.row >= 0, indexPath.row < numberOfRows(inSection: indexPath.section) else { return false }
    return true
}

3. 避免数据源竞态问题

所有UITableView数据源的修改必须在主线程执行。如果异步块执行期间数据源可能被修改,建议在执行scrollToRow前重新计算row和section,不要复用之前的变量,确保和当前数据源状态匹配。

4. 异常捕获作为兜底方案

如果无法完全复现问题,可以给scrollToRow加异常捕获,避免崩溃扩散:

DispatchQueue.main.async { [weak self] in
    guard let self = self else { return }
    let section = self.numberOfSections - 1
    guard section >= 0 else { return }
    let row = self.numberOfRows(inSection: section) - 1
    guard row >= 0 else { return }
    
    let indexPath = IndexPath(row: row, section: section)
    if self.hasRowAtIndexPath(indexPath: indexPath) {
        do {
            try self.tableView.scrollToRowSafely(at: indexPath, at: .bottom, animated: isAnimated)
        } catch {
            // 记录日志用于后续排查
            print("Scroll failed: \(error.localizedDescription)")
        }
    }
}

extension UITableView {
    func scrollToRowSafely(at indexPath: IndexPath, at scrollPosition: UITableView.ScrollPosition, animated: Bool) throws {
        guard indexPath.section < numberOfSections, indexPath.row < numberOfRows(inSection: indexPath.section) else {
            throw NSError(domain: "UITableViewError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid IndexPath"])
        }
        self.scrollToRow(at: indexPath, at: scrollPosition, animated: animated)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 15:30:58