iOS开发:UITableView无法展示Firebase数据,调用reloadData后单元格堆叠
问题原因&解决方案
你遇到的问题由两个核心错误导致,分别对应修改即可:
1. 单元格堆叠问题修复
堆叠根本原因是你没有给UITableView指定行高,同时自定义cell的子视图添加逻辑错误:
- 先修改
AssignmentCellTableViewCell,把子视图初始化从setSelected移到初始化方法,避免重复添加视图,同时避免变量名和系统属性冲突:
import UIKit class AssignmentCellTableViewCell: UITableViewCell { lazy var backview: UIView = { let view = UIView(frame: CGRect(x: 10, y: 6, width: 340, height: 110)) view.backgroundColor = UIColor.white return view }() lazy var customImageView: UIImageView = { let image = UIImageView(frame: CGRect(x: 4, y: 15, width: 80, height: 80)) image.contentMode = .scaleAspectFill return image }() lazy var assignmentname: UILabel = { let assignmentname = UILabel(frame: CGRect(x: 116, y: 8, width: backview.frame.width - 88, height: 25)) assignmentname.textAlignment = .left assignmentname.font = UIFont.boldSystemFont(ofSize: 20) return assignmentname }() lazy var duedate: UILabel = { let duedate = UILabel(frame: CGRect(x: 116, y: 42, width: backview.frame.width - 88, height: 25)) duedate.textAlignment = .left duedate.font = UIFont.systemFont(ofSize: 10) return duedate }() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) setupSubviews() } required init?(coder: NSCoder) { super.init(coder: coder) setupSubviews() } private func setupSubviews() { contentView.addSubview(backview) backview.addSubview(customImageView) backview.addSubview(assignmentname) backview.addSubview(duedate) backgroundColor = .clear contentView.backgroundColor = .clear } override func layoutSubviews() { super.layoutSubviews() // 适配不同屏幕宽度 backview.frame = CGRect(x: 10, y: 6, width: contentView.bounds.width - 20, height: 110) backview.layer.cornerRadius = 15 backview.clipsToBounds = true backview.layer.borderColor = UIColor.systemGray5.cgColor backview.layer.borderWidth = 1 customImageView.layer.cornerRadius = 40 customImageView.clipsToBounds = true } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // 移除原有addSubview逻辑 } }
- 然后在
setTableView方法里添加行高配置:
func setTableView() { assignmentstableview.backgroundColor = UIColor.clear assignmentstableview.delegate = self assignmentstableview.dataSource = self // 固定行高和你自定义cell的总高度匹配:6+110+6=122 assignmentstableview.rowHeight = 122 assignmentstableview.estimatedRowHeight = 0 assignmentstableview.register(AssignmentCellTableViewCell.self, forCellReuseIdentifier: "Cell") }
2. Firebase数据拉取逻辑修复
你原来的逻辑在循环遍历每条Firebase数据时都调用reloadData和setTableView,会导致多次重复刷新,同时viewDidAppear重复调用syncAssignments会导致数据重复,修改如下:
- 首先调整
viewDidLoad执行顺序,先配置TableView再加载数据:
override func viewDidLoad() { super.viewDidLoad() // 先配置TableView setTableView() // 测试数据可以保留 data.append(assignmentmodal(name: "test2", duedate: "test2", imagename: "")) syncAssignments() // 原有其他逻辑不变 titleLabel.text = "\(ClassesViewController.shared.chosenClass)" // ... 剩余原有代码不需要修改 }
- 修改
syncAssignments方法,先清空旧数据,全部加载完成后统一刷新:
func syncAssignments() { // 先清空旧数据避免重复 self.data.removeAll() db.collection("Classes").document(ClassesViewController.shared.chosenClass).collection("Assignments").getDocuments() { [weak self] (querySnapshot, err) in guard let self = self else { return } if let err = err { print("Error getting documents: \(err)") } else { // 先循环处理完全部数据 for document in querySnapshot!.documents { if let name = document.get("name"), let duedate = document.get("due date") { self.data.append(assignmentmodal(name: "\(name)", duedate: "\(duedate)", imagename: "")) } } // 切主线程统一刷新UI DispatchQueue.main.async { self.assignmentstableview.reloadData() } } } }
- 对应的
cellForRowAt方法里修改图片属性名即可:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let assignments = data[indexPath.row] let cell = assignmentstableview.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! AssignmentCellTableViewCell cell.customImageView.image = UIImage(named: assignments.imagename) cell.assignmentname.text = assignments.name cell.duedate.text = assignments.duedate return cell }
内容的提问来源于stack exchange,提问作者Kiran Lim
相关产品推荐
相关产品推荐

