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

Swift3中TableView下拉刷新触发Index out of range崩溃求助

问题排查与解决方案

先看你遇到的崩溃报错 Thread 1: Fatal error: Index out of range,这是典型的数组越界问题,结合你的代码,我梳理出几个核心问题,分前端和后端两部分说明:

一、前端代码的关键问题

1. 数组大小写拼写错误(直接导致崩溃)

你在给cell.labelDepartamento赋值时写的是self.Departamento[indexPath.row],但你定义的数组是var departamento = [String]()(小写d开头)!这种大小写不匹配会导致访问一个未初始化的空数组,当用户数≥6时,表格滚动到对应行就触发了越界崩溃。

2. 多数组同步风险

你用多个独立数组存储用户的不同字段,这种方式很容易出现数组长度不一致的情况(比如某个字段解析失败没添加到数组),进而引发越界。更合理的做法是用结构体统一管理用户数据。

3. 缺少越界安全检查

在tableView(_:cellForRowAt:)方法里,你直接访问数组下标,没有先判断下标是否在合法范围内,这是不安全的。

前端修复方案

第一步:修正拼写错误

把self.Departamento[indexPath.row]改成self.departamento[indexPath.row],先解决最直接的崩溃问题。

第二步:改用结构体管理用户数据

替换原来的多个独立数组,用一个结构体来封装用户信息,避免同步问题:

// 定义用户结构体
struct User {
    let id: String
    let nombre: String
    let pais: String
    let departamento: String
    let municipio: String
    let direccion: String
    let telefono: String
    let celular: String
    let email: String
}

// 替换所有独立数组
var users = [User]()

然后在JSON解析逻辑里,填充这个结构体数组:

for result in json {
    let id = (result["id"] as? String) ?? "no proporcionado"
    let nombres = (result["nombres"] as? String) ?? "no proporcionado"
    let pais = (result["pais"] as? String) ?? "no proporcionado"
    let departamento = (result["depto"] as? String) ?? "no proporcionado"
    let municipio = (result["municipio"] as? String) ?? "no proporcionado"
    let direccion = (result["direccion"] as? String) ?? "no proporcionado"
    let telefono = (result["telefono"] as? String) ?? ""
    let celular = (result["celular"] as? String) ?? ""
    let email = (result["email"] as? String) ?? ""
    
    let user = User(id: id, nombre: nombres, pais: pais, departamento: departamento, municipio: municipio, direccion: direccion, telefono: telefono, celular: celular, email: email)
    self.users.append(user)
}

表格数据源方法里的取值逻辑也改成:

guard indexPath.row < users.count else {
    // 下标越界时返回空cell,避免崩溃
    return cell
}
let user = users[indexPath.row]
cell.labelNombres.text = user.nombre
cell.labelDepartamento.text = user.departamento

第三步:优化请求并发问题

添加一个任务变量,避免下拉刷新时并发请求导致数据混乱:

// 定义全局任务变量
var dataTask: URLSessionDataTask?

@objc func getDatos(){
    dataTask?.cancel() // 取消未完成的旧请求
    self.users.removeAll()
    
    // ... 你的请求代码 ...
    
    dataTask = task
    task.resume()
}

二、后端代码的冗余问题

你的后端代码里有一段完全没用的冗余代码(getCats函数和$categorias数组),虽然不会直接导致前端崩溃,但会增加代码复杂度,建议删掉:

// 删掉以下冗余代码
$categorias = array();
function getCats($col, $row) {
    $categorias[$col['id']] = $row['id'];
    $categorias[$col['nombres']] = $row['nombres'];
    $categorias[$col['pais']] = $row['pais'];
    $categorias[$col['depto']] = $row['depto'];
    $categorias[$col['municipio']] = $row['municipio'];
    $categorias[$col['direccion']] = $row['direccion'];
    $categorias[$col['telefono']] = $row['telefono'];
    $categorias[$col['celular']] = $row['celular'];
    $categorias[$col['email']] = $row['email'];
}
array_push($categorias, $results);

保留核心的查询和JSON输出即可:

$statement=$conn->prepare("SELECT id, CONCAT(nombres, ' ', apellidos) AS nombres, pais, depto, municipio, direccion, telefono, celular, email FROM USERS");
$statement->execute();
$results=$statement->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($results);

总结

最直接引发崩溃的原因是前端数组大小写拼写错误,修复后崩溃应该会立即消失。而改用结构体管理用户数据,能从根本上避免多数组同步的风险,让代码更健壮。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:32:45