Swift 4中tableView的cellForRowAt方法跳过最后一行问题咨询
你遇到的情况确实有点费解——明明numberOfRowsInSection返回了14(对应coins数组的元素数),但cellForRowAt只执行到索引12,总共13次。我来帮你梳理几个最可能的原因和排查方向:
1. 最核心的问题:cellForRowAt没有返回单元格
看你贴出来的cellForRowAt代码,最后居然漏掉了return celula这一行!这可是致命错误!
UITableView要求这个方法必须返回一个有效的UITableViewCell实例,如果没有返回值,系统会认为当前单元格创建失败,可能直接终止后续的单元格渲染流程,自然就不会走到第14行(索引13)了。
你需要补全这行代码:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let celula = tableView.dequeueReusableCell(withIdentifier: "cellCoin", for: indexPath) as! CoinTableViewCell print("row " + String(indexPath.row)) let coin = coins[indexPath.row] investment = coin.value(forKey: "investment") as! Double viewTotalInvestment += investment // 必须返回单元格! return celula }
2. TableView的可视范围被截断
如果tableView的高度被父视图约束限制,或者底部被其他UI元素挡住,最后一行可能不在可视区域内,系统会懒加载不渲染它。你可以试试:
- 手动滚动tableView到底部,看看此时会不会触发索引13的
cellForRowAt调用 - 检查tableView的约束,确保它的底部没有被截断,contentSize足够容纳14行
3. 数据源数组coins被动态修改
虽然你说数组初始有14个元素,但有可能在numberOfRowsInSection调用后,coins被其他代码悄悄修改(比如移除了最后一个元素)。你可以在两个方法里都打印数组长度验证:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { let count = self.coins.count print("numberOfRows: \(count)") return count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { print("current coins count: \(self.coins.count)") // 其他代码... }
如果两个打印的数字不一致,说明数组在运行时被修改了。
4. 行高估算错误(自动布局场景)
如果你的tableView使用自动布局计算行高,且estimatedRowHeight设置得和实际行高差距太大,可能会导致系统错误计算contentSize,误以为不需要渲染最后一行。你可以尝试:
- 手动设置固定的
rowHeight代替自动计算 - 把
estimatedRowHeight调整为更接近实际行高的值
5. 单元格复用或注册问题
虽然概率较低,但如果单元格标识符"cellCoin"注册错误,或者复用池出现异常,也可能导致部分单元格无法创建。你可以暂时禁用复用(直接创建新cell)来测试:
let celula = CoinTableViewCell(style: .default, reuseIdentifier: "cellCoin")
如果这样能渲染出14行,说明复用环节有问题,需要检查单元格注册代码。
内容的提问来源于stack exchange,提问作者Mucida

