You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Table View无法显示从Firebase获取的数据问题求助

问题描述

尝试将Firebase数据显示到Table View时遇到困难,自认为代码逻辑正确,但数据始终无法正常显示。已尝试多日,求帮忙排查问题。

数据库结构截图

Database Structure 1
Database Structure 2

应用界面截图(Table View无数据)

App View with the Table View

相关代码

import UIKit
import Firebase

class InserisciViewController: UIViewController {
    
    
    @IBOutlet weak var labelTutorialInserisci: UILabel!
    @IBOutlet weak var buttonEntrate: UIButton!
    @IBOutlet weak var buttonUscite: UIButton!
    @IBOutlet weak var tableView: UITableView!
    
    var transactions: [Transaction] = []
    
    let db = Firestore.firestore()
    
    let user = Auth.auth().currentUser
    
    // 定义交易结构体
    struct Transaction {
        let userId: String
        let name: String
        let type: TransactionType
        let amount: Double
        let date: Date
    }

    // 定义交易类型枚举
    enum TransactionType {
        case positive
        case negative
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        title = K.Generic_Text.scrittaInserisci
        navigationItem.hidesBackButton = true
        
        labelTutorialInserisci.text = K.App_Text.tutorialInserisci
        
        
        // 首先获取"utenti"集合引用
        let utentiCollectionRef = Firestore.firestore().collection("utenti")

        // 查询每个用户的"positive"和"negative"集合
        utentiCollectionRef.getDocuments { (snapshot, error) in
            if let error = error {
                print("获取文档错误: \(error.localizedDescription)")
                return
            }

            var transactions: [Transaction] = []

            for _ in snapshot!.documents {
                // 获取当前用户ID
                let userId = self.user!.uid

                
                // 查询"positive"集合中最新的一条记录(按日期倒序)
                let positiveCollectionRef = utentiCollectionRef.document(self.user!.uid).collection("transactions").document("transactions").collection("positive")
                positiveCollectionRef.order(by: "data", descending: true).limit(to: 1).getDocuments { (snapshot, error) in
                    if let error = error {
                        print("获取文档错误: \(error.localizedDescription)")
                        return
                    }

                    // 解析数据并添加到交易数组
                    for document in snapshot!.documents {
                        let data = document.data()
                        let name = data["name"] as! String
                        let number = data["number"] as! Double
                        let date = data["data"] as! Timestamp
                        transactions.append(Transaction(userId: userId, name: name, type: .positive, amount: number, date: date.dateValue()))
                    }
                }

                // 查询"negative"集合中最新的一条记录(按日期倒序)
                let negativeCollectionRef = utentiCollectionRef.document(self.user!.uid).collection("transactions").document("transactions").collection("negative")
                negativeCollectionRef.order(by: "data", descending: true).limit(to: 1).getDocuments { (snapshot, error) in
                    if let error = error {
                        print("获取文档错误: \(error.localizedDescription)")
                        return
                    }

                    // 解析数据并添加到交易数组
                    for document in snapshot!.documents {
                        let data = document.data()
                        let name = data["name"] as! String
                        let number = data["number"] as! Double
                        let date = data["data"] as! Timestamp
                        transactions.append(Transaction(userId: userId, name: name, type: .negative, amount: number, date: date.dateValue()))
                    }
                }
            }

            // 所有查询完成后,按日期排序并刷新Table View
            transactions.sort { $0.date > $1.date }
            self.tableView.reloadData()
        }

    }
    
}

日志截图

Logs


问题排查与修复方案

核心问题1:异步请求时序错误

Firestore的getDocuments是异步操作,你在发起两个异步查询后立刻执行排序和刷新Table View的代码,但此时异步请求还未完成,transactions数组仍为空,导致Table View无数据。

核心问题2:局部变量覆盖全局数组

闭包内部声明的var transactions: [Transaction] = []覆盖了类的全局transactions数组,即使异步请求获取到数据,也不会更新到Table View依赖的数据源中。

核心问题3:不必要的全用户遍历

先获取utenti集合所有文档再循环查询当前用户数据完全多余,直接针对当前用户ID查询即可。

核心问题4:未设置Table View数据源与代理

类未遵守UITableViewDataSource协议,也未设置tableView.dataSource = self,Table View无法获取行数和单元格数据。

修复后的代码

import UIKit
import Firebase

class InserisciViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
    @IBOutlet weak var labelTutorialInserisci: UILabel!
    @IBOutlet weak var buttonEntrate: UIButton!
    @IBOutlet weak var buttonUscite: UIButton!
    @IBOutlet weak var tableView: UITableView!
    
    var transactions: [Transaction] = []
    
    let db = Firestore.firestore()
    
    let user = Auth.auth().currentUser
    
    struct Transaction {
        let userId: String
        let name: String
        let type: TransactionType
        let amount: Double
        let date: Date
    }

    enum TransactionType {
        case positive
        case negative
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        title = K.Generic_Text.scrittaInserisci
        navigationItem.hidesBackButton = true
        labelTutorialInserisci.text = K.App_Text.tutorialInserisci
        
        // 设置Table View数据源与代理
        tableView.dataSource = self
        tableView.delegate = self
        
        fetchTransactions()
    }
    
    private func fetchTransactions() {
        guard let userId = user?.uid else {
            print("用户未登录")
            return
        }
        
        // 构造两个集合的查询引用
        let positiveRef = db.collection("utenti").document(userId)
            .collection("transactions").document("transactions").collection("positive")
            .order(by: "data", descending: true).limit(to: 1)
        
        let negativeRef = db.collection("utenti").document(userId)
            .collection("transactions").document("transactions").collection("negative")
            .order(by: "data", descending: true).limit(to: 1)
        
        // 使用DispatchGroup等待两个异步请求完成
        let group = DispatchGroup()
        
        group.enter()
        positiveRef.getDocuments { [weak self] snapshot, error in
            defer { group.leave() }
            guard let self = self, let snapshot = snapshot, error == nil else {
                print("获取positive数据失败: \(error?.localizedDescription ?? "未知错误")")
                return
            }
            
            for doc in snapshot.documents {
                let data = doc.data()
                guard let name = data["name"] as? String,
                      let number = data["number"] as? Double,
                      let timestamp = data["data"] as? Timestamp else {
                    continue
                }
                self.transactions.append(Transaction(userId: userId, name: name, type: .positive, amount: number, date: timestamp.dateValue()))
            }
        }
        
        group.enter()
        negativeRef.getDocuments { [weak self] snapshot, error in
            defer { group.leave() }
            guard let self = self, let snapshot = snapshot, error == nil else {
                print("获取negative数据失败: \(error?.localizedDescription ?? "未知错误")")
                return
            }
            
            for doc in snapshot.documents {
                let data = doc.data()
                guard let name = data["name"] as? String,
                      let number = data["number"] as? Double,
                      let timestamp = data["data"] as? Timestamp else {
                    continue
                }
                self.transactions.append(Transaction(userId: userId, name: name, type: .negative, amount: number, date: timestamp.dateValue()))
            }
        }
        
        // 所有请求完成后,排序并刷新Table View
        group.notify(queue: .main) { [weak self] in
            guard let self = self else { return }
            self.transactions.sort { $0.date > $1.date }
            self.tableView.reloadData()
        }
    }
    
    // MARK: - UITableViewDataSource
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return transactions.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // 替换成你在Storyboard中设置的Cell标识符
        let cell = tableView.dequeueReusableCell(withIdentifier: "TransactionCell", for: indexPath)
        let transaction = transactions[indexPath.row]
        cell.textLabel?.text = transaction.name
        cell.detailTextLabel?.text = "\(transaction.type == .positive ? "+" : "-")\(transaction.amount)"
        return cell
    }
}

额外注意事项

  • 确保Storyboard中Table View的Cell已设置正确的标识符,并与代码中dequeueReusableCell的参数一致。
  • 用可选绑定替代强制解包(as!换成as?),避免因数据格式错误导致崩溃。
  • 使用[weak self]避免循环引用,防止内存泄漏。

内容的提问来源于stack exchange,提问作者Mike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 15:40:10