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

