Firestore数据获取与TableView展示异常及页面重复跳转问题
解决iOS Firebase数据展示异常与重复跳转问题
老哥,我看你这遇到两个头疼的问题:数据加载后TableView不展示,点击按钮还会重复跳转出带空行的目标VC。咱们一步步拆解解决:
一、先搞定重复跳转的问题
这个大概率是触发逻辑重复导致的,排查这几点:
- 检查Storyboard的Segue绑定:如果之前你是直接从按钮拖拽Segue到
ViewControllerForTable,现在又在IBAction里手动调用performSegue,就会触发两次跳转。打开Storyboard,选中按钮,在右侧Connections Inspector里删掉多余的Segue,只保留IBAction的绑定。 - 检查IBAction重复绑定:确认按钮只绑定了一次IBAction——不管是Storyboard拖拽的,还是代码里
addTarget(_:action:for:)添加的,都要保证只执行一次(比如把addTarget放在viewDidLoad里,别放在viewWillAppear这种会重复执行的生命周期里)。 - 跳转代码只在数据准备好后执行:别在IBAction里直接跳转,要等Firestore数据和Storage图片都加载完成后再触发跳转,避免多次触发。
二、解决数据不展示的问题
核心是异步操作的顺序和数据传递的正确性,按以下步骤排查:
1. 先确认Firestore数据能正常获取
先加日志打印,确保你能拿到title、description、imageURL:
func fetchFirestoreData() { let db = Firestore.firestore() db.collection("your-collection-name").getDocuments { snapshot, error in guard let docs = snapshot?.documents, error == nil else { print("Firestore数据获取失败:\(error?.localizedDescription ?? "未知错误")") return } // 打印每一条数据,确认字段存在且类型正确 docs.forEach { print("获取到数据:\($0.data())") } // 拿到数据后再处理图片下载 self.downloadImages(from: docs) } }
2. 用DispatchGroup处理异步图片下载
因为Storage下载图片是异步操作,直接循环会导致数组还没填充完就传给TableVC。用DispatchGroup等待所有图片下载完成:
var cellDataArray = [Cella]() // 你的Cella对象数组 func downloadImages(from documents: [QueryDocumentSnapshot]) { let group = DispatchGroup() cellDataArray.removeAll() // 清空旧数据 for doc in documents { group.enter() // 先解析Firestore字段(注意字段名大小写要完全匹配!) guard let title = doc["title"] as? String, let desc = doc["description"] as? String, let imageURLStr = doc["imageURL"] as? String else { print("字段解析失败,跳过这条数据") group.leave() continue } // 从Storage下载图片 let storageRef = Storage.storage().reference(forURL: imageURLStr) storageRef.getData(maxSize: 10 * 1024 * 1024) { data, error in defer { group.leave() } // 不管成功失败都要leave guard let imageData = data, let image = UIImage(data: imageData), error == nil else { print("图片下载失败:\(error?.localizedDescription ?? "未知错误")") return } // 创建Cella对象并加入数组 let cellItem = Cella(title: title, description: desc, image: image) self.cellDataArray.append(cellItem) } } // 所有异步操作完成后,再跳转并传递数据 group.notify(queue: .main) { print("所有数据准备完成,数组长度:\(self.cellDataArray.count)") self.navigateToTableVC() } }
3. 正确传递数据到TableVC
在group.notify里执行跳转,确保数组已经填充完毕:
@IBAction func triggerButtonTapped(_ sender: UIButton) { fetchFirestoreData() // 先触发数据加载,等完成后再跳转 } private func navigateToTableVC() { guard let tableVC = storyboard?.instantiateViewController(withIdentifier: "ViewControllerForTable") as? ViewControllerForTable else { print("找不到目标VC") return } tableVC.cellData = self.cellDataArray // 给TableVC的数据源属性赋值 navigationController?.pushViewController(tableVC, animated: true) }
4. 检查TableView的数据源配置
确保ViewControllerForTable里的TableView设置正确:
class ViewControllerForTable: UIViewController, UITableViewDataSource { var cellData = [Cella]() @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() tableView.dataSource = self // 注册自定义Cell(如果用的话) tableView.register(UINib(nibName: "YourCustomCell", bundle: nil), forCellReuseIdentifier: "CustomCellID") // 自动计算Cell高度,避免空行 tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 120 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return cellData.count // 这里一定要返回数组长度,不然会显示空行 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCellID", for: indexPath) as! YourCustomCell let item = cellData[indexPath.row] cell.titleLabel.text = item.title cell.descLabel.text = item.description cell.iconImageView.image = item.image return cell } }
最后排查小细节
- 确认Firestore的字段名和你代码里解析的完全一致(大小写敏感!比如Firestore里是
Title,代码里写title就会解析失败)。 - 检查Storage的图片权限,确保你的App有权限下载对应图片。
- 如果还是有空行,检查TableView的
separatorStyle是不是设置成了none之外的样式,或者自定义Cell的约束是否正确(比如没有给Label设置高度约束导致内容不显示)。
内容的提问来源于stack exchange,提问作者Niccolò Diana
相关产品推荐
相关产品推荐

