【问题标题】:Populating tableview with firebase data (array not updating within .childAdded)使用 firebase 数据填充 tableview(数组未在 .childAdded 中更新)
【发布时间】:2020-07-26 10:54:32
【问题描述】:

我知道帖子的标题令人困惑,但我希望在这里澄清一下。

我的最终目标:

基本上,我想使用从 firebase 实时数据库获得的数据填充一个 tableview。

我的问题

通过大量的故障排除,我相信我的问题是,当我在 .childAdded 闭包内的 modelObjectsArray 中附加一些内容时,它似乎并没有真正更新数组。

我的代码

视图控制器

import Foundation
import UIKit
import Firebase

class CategoryDetailViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    @IBOutlet weak var tableView: UITableView!
    static let cellReuseIdentifier = "ratingCell"
    
    var modelObjectArray: [Rating] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        retrieveData()
        print(modelObjectArray) // prints [] for some reason...
//        print(modelObjectArray.count) // prints 0     
        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        
        tableView.delegate = self
        tableView.dataSource = self
        
//        modelObjectArray.append(Rating(score: 3, comment: "hahahaha, I really do enjoy beans...", timestamp: "Just now", likes: 10)) -> temporary to see if the tableview works (which it does)
        tableView.reloadData()
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return modelObjectArray.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell: CategoryDetailTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "ratingCell") as! CategoryDetailTableViewCell
        
        let modelObject = self.modelObjectArray[indexPath.row]
        cell.commentLabel.text = modelObject.comment
        cell.timestampLabel.text = String(modelObject.timestamp) + " hours ago"
        cell.ratingLabel.text = String(modelObject.score) + "/10"
        
        return cell
    }
    
    func retrieveData(){
        let databaseRef: DatabaseReference = Database.database().reference()
        databaseRef.child("uid").child("categories").child("looks").child("ratings").observe(.childAdded, with: { snapshot in
            if let value = snapshot.value as? [String:Any] {
                let rating = Rating(score: value["score"] as? Int ?? 0, comment: value["comment"] as? String ?? "", timestamp: value["creationDate"] as? String ?? "Just now", likes: value["likes"] as? Int ?? 0)
                self.modelObjectArray.append(rating)
                print(self.modelObjectArray.count) // prints 2

            }
        })
        self.tableView.reloadData()
    }

}

评级模型

class Rating {
    var score: Int
    var comment: String
    var timestamp: String
    var likes: Int
    
    init(score: Int, comment: String, timestamp: String, likes: Int) {
        self.score = score
        self.comment = comment
        self.timestamp = timestamp
        self.likes = likes
    }
}

我的 Firebase

https://imgur.com/a/S73DoON

总体

我觉得我遗漏了太多信息,所以如果您需要更多信息,请告诉我。 (也希望我在为帖子清理它时没有删除任何重要代码 - 只是告诉我是否可能)

无论如何,提前感谢任何回答的人!

【问题讨论】:

    标签: ios swift firebase firebase-realtime-database


    【解决方案1】:

    在异步块中重新加载数据 .. 否则在从 firebase 获取数据之前执行重新加载数据

     func retrieveData(){
            let databaseRef: DatabaseReference = Database.database().reference()
            databaseRef.child("uid").child("categories").child("looks").child("ratings").observe(.childAdded, with: { snapshot in
                if let value = snapshot.value as? [String:Any] {
                    let rating = Rating(score: value["score"] as? Int ?? 0, comment: value["comment"] as? String ?? "", timestamp: value["creationDate"] as? String ?? "Just now", likes: value["likes"] as? Int ?? 0)
                    self.modelObjectArray.append(rating)
                    print(self.modelObjectArray.count) // prints 2
    
                     self.tableView.reloadData()
                    
                }
            })
           
        }
    

    第二种方法是使用完成处理程序

    func retrieveData(completion:@escaping (Bool)->Void) {
        let databaseRef: DatabaseReference = Database.database().reference()
        databaseRef.child("uid").child("categories").child("looks").child("ratings").observe(.childAdded, with: { snapshot in
            if let value = snapshot.value as? [String:Any] {
                let rating = Rating(score: value["score"] as? Int ?? 0, comment: value["comment"] as? String ?? "", timestamp: value["creationDate"] as? String ?? "Just now", likes: value["likes"] as? Int ?? 0)
                self.modelObjectArray.append(rating)
                print(self.modelObjectArray.count) // prints 2
    
                completion(true)
                
            }else {
                  completion(false)
            }
        })
       
    } 
    

    这样使用

    override func viewDidLoad() {
            super.viewDidLoad()
            retrieveData { [weak self] (isSuccess) in
                self?.tableViewe.reloadData()
            }
            
            // Do any additional setup after loading the view.
        }
    

    【讨论】:

    • 非常感谢您的回答!第一种方法可行,但是第二种方法更好吗?
    • 但在我看来....是的,第二个是更好的方法
    猜你喜欢
    • 1970-01-01
    • 2018-11-22
    • 2020-06-06
    • 2021-04-27
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    • 2016-11-09
    • 1970-01-01
    相关资源
    最近更新 更多