Swift中tableView.reloadData()在viewDidLoad/代理中无效,点击按钮正常?
嘿,我来帮你拆解下这个问题~ 你遇到的情况其实很常见,核心原因大概率和数据源状态或者tableView的渲染逻辑有关,结合你给出的代码,我整理了几个关键排查点:
1. 初始数据源是否为空?
这是最常见的诱因!你在viewDidLoad里把exerciseList赋值为ExerciseListTableViewController.ExerciseList,如果这个静态列表初始是空的,那tableView(numberOfRowsInSection:)会返回0——系统自然不会去调用cellForRowAtIndexPath,毕竟没有单元格需要渲染嘛。
而按钮点击事件里,你执行了exerciseList.append(Exercise()),这时候exerciseList的count变成了1,调用reloadData()后,numberOfRowsInSection返回1,所以cellForRowAtIndexPath就正常触发了。
你可以在viewDidLoad末尾加个打印验证:
print("初始exerciseList数量:\(exerciseList.count)") print("初始trainingList数量:\(trainingList.count)")
2. 代理/数据源设置的时机是否有问题?
你在viewDidLoad里设置了tableView.delegate = self和tableView.dataSource = self,这本身是没问题的,但要确认:
tableView的IBOutlet是否正确连接?如果没连,那不管在哪调用reloadData()都没用,但你按钮点击能工作,说明这个可以排除。- 有没有在其他地方意外重置了delegate/dataSource?比如某个方法里把它们设成了nil?不过从你的代码来看暂时没发现这种情况。
3. 代理方法reload(choose: Bool)的调用时机与数据源关联
这个协议方法里改变了exerciseTableChoose,然后调用reloadData()。你需要确认:
当调用这个方法时,exerciseTableChoose对应的数据源(比如exerciseList或trainingList)是否有数据?
比如如果choose为true时用exerciseList,但此时exerciseList是空的,那numberOfRowsInSection还是返回0,cellForRowAtIndexPath不会触发。
快速调试技巧
给你几个定位问题的小方法:
- 在
numberOfRowsInSection和cellForRowAtIndexPath方法里加打印日志,看看调用reloadData()时,这两个方法的调用情况:func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { let count = exerciseTableChoose ? exerciseList.count : trainingList.count print("当前返回行数:\(count)") return count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { print("触发cellForRow:\(indexPath.row)") // 你的cell创建逻辑 } - 如果发现
numberOfRowsInSection返回0,就去对应数据源找原因——是不是初始没赋值、或者赋值的数据源本身为空?
总结
最可能的情况就是初始数据源为空,导致reloadData()后没有单元格需要渲染,所以cellForRowAtIndexPath没被触发;而按钮点击给数据源加了数据,才让渲染逻辑正常运行。
内容的提问来源于stack exchange,提问作者Александр Гребиноа

