【问题标题】:How to reload UITableView data after Firebase finishes dowload of user data?Firebase 完成用户数据下载后如何重新加载 TableView 数据?
【发布时间】:2017-01-22 01:27:45
【问题描述】:

所以我对 firebase 有疑问,因为它是异步的,我不知道如何正确使用它。我的应用程序有待售产品的提要,这些提要是从 firebase 数据库和 firebase 存储(图片)中获取的。问题是我不知道何时或如何重新加载我的 UITableView 以获取所有数据而不会出现 nil 错误。而且它更复杂,因为首先我需要从 firebase 获取我的 salePost 信息,然后才能获取也在 tableview 单元格中的用户信息。

这就是我获得销售帖子的方式

    func getSalePosts() -> [SalePost]{

    var salePosts = [SalePost]()

    FIR_DATABASE_SALE_POSTS.queryLimitedToFirst(NUMBER_OF_LOADED_POSTS).observeEventType(.Value, withBlock: { (snapshot) in

        for snap in snapshot.children{

            let imgString = snap.value["image"] as! String!
            let imgNSURL = NSURL(string: imgString)
            let imgNSDATA = NSData(contentsOfURL: imgNSURL!)

            let downloadedImg = UIImage(data: imgNSDATA!)

            let newSalePost = SalePost(title: snap.value["title"] as! String!,
                userUID: snap.value["authorUID"] as! String!,
                postBody: snap.value["body"] as! String!,
                amountAvailable: snap.value["amountAvailable"] as! String!,
                unit: snap.value["unit"] as! String!,
                price: snap.value["price"] as! String!,
                image: downloadedImg!)

            salePosts.append(newSalePost)
            print("num of posts \(salePosts.count)")
        }

    }) { (error) in
            print(error.localizedDescription)
    }

    return salePosts
}

这是获取 UserInfo 的函数(我将从 salePost 对象获取“userUID”)

    func getProducer(userUID:String) -> Producer{


    var newProducer:Producer?

    FIR_DATABASE_USERS.child(userUID).observeEventType(.Value, withBlock: { (snap) in

        print(snap.description)

        let imgString = snap.value!["profilePic"] as! String!
        let imgNSURL = NSURL(string: imgString)
        let imgNSDATA = NSData(contentsOfURL: imgNSURL!)
        let downloadedImg = UIImage(data: imgNSDATA!)


        let someProducer = Producer(
            displayName: snap.value!["displayName"] as! String!,
            address: snap.value!["address"] as! String!,
            mobile: snap.value!["mobile"] as! String!,
            email: snap.value!["email"] as! String!,
            password: "",
            bio: snap.value!["bio"] as! String!,
            profilePic: downloadedImg!,
            openingHour: snap.value!["openingHour"] as! String!,
            closingHour: snap.value!["closingHour"] as! String!)

        newProducer = someProducer
        print(newProducer?.description)

        }) { (error) in
            print(error.localizedDescription)
    }

    return newProducer!
}

正如我所说,我不知道何时、何地以及如何调用这些函数(在我的提要控制器中)以使其“同步”并将所有数据正确地传递给 tableview 单元格。我会感激每一个帮助。我试过谷歌它,甚至在这里找到它,但没有任何帮助。

【问题讨论】:

  • 你的 cellforrowatindexpath 方法是什么样子的?
  • 您不能从包含异步任务的方法中返回某些内容。使用完成处理程序。 SO上有数百个相关问题。
  • @vadian 谢谢!完成处理程序为我工作!

标签: ios swift asynchronous firebase firebase-realtime-database


【解决方案1】:

创建所有salePosts 后,您应该调用tableView.reloadData()。因此,在您循环创建将newSalePost 附加到salePosts 的位置之后。由于这是一个异步调用,在函数末尾返回您的 salePosts 是没有用的。

我假设您的 viewController 有一个属性 tableView,并且您将 tableViewdelegatedatasource 设置为您的 viewController

不要忘记在主线程上调用tableView.reloadData()

例如:Dispatch.main.async { self.tableView.reloadData() }.

【讨论】:

    【解决方案2】:

    对于看到这篇文章的未来用户,您还可以使用 Dispatch 组来处理从 Firebase 检索数据的异步属性。有关调度组工作的更多信息,您可以阅读Dispatch Groups in Swift 3。 Swift 4 中的语法也大致相同。这就是我使用 tableview 为我的项目实现调度的方式。

    var anEmptyArray: [String] = []
    var dbRef: DatabaseReference!
    
    @IBOutlet weak var myTable: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        retrieveDataFromDatabase()
    }
    
    func retrieveDataFromDatabase() {
        dbRef = Database.database().reference().child("user")
        dbRef.observe(.value, with: { snapshot in
            let group = DispatchGroup()
            let enumerator = snapshot.children
    
            while let rest = enumerator.nextObject() as? DataSnapshot {
                group.enter()
                self.categories.append(rest.value as! String)
                group.leave()
            }
            group.notify(queue: .main) {
                self.categoryTable.reloadData()
            }
        })
    
    }
    

    我使用了 snapshot.children,因为我是如何构建数据的。您如何获取快照将取决于您拥有的结构。调度组必须在 dbRef.observe 闭包中使用。

    【讨论】:

      猜你喜欢
      • 2014-12-17
      • 2017-07-25
      • 2020-02-28
      • 2020-11-13
      • 2016-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-09
      相关资源
      最近更新 更多