【问题标题】:Reload TableView data only after downloading everything from the firebase database Swift仅在从 Firebase 数据库 Swift 下载所有内容后重新加载 TableView 数据
【发布时间】:2020-02-28 15:41:20
【问题描述】:

我一直在寻找一段时间,但我不知道如何处理这个问题。 我有一个 Firebase 数据库,其中包含一些数据以及存储到存储中的图像链接。 我希望在从数据库下载每张图片后重新加载我的 UICollectionView,而不仅仅是第一个。

newRef.observeSingleEvent(of: .value, with: { (snapshotOne) in
        for child in snapshotOne.children {
            let snap = child as! DataSnapshot
            let key = snap.key

            newRef.child(key).observeSingleEvent(of: .value, with: { (snapshotTwo) in
                for child in snapshotTwo.children {
                    let snappotto = child as! DataSnapshot
                    var imageDownloaded: UIImage?

                    if let dictionary = snappotto.value as? [String : AnyObject] {
                        let url = URL(string: dictionary["imageURL"] as! String)
                        URLSession.shared.dataTask(with: url!) { (data, response, error) in
                            if error != nil {
                                print("[Error]: \(String(describing: error))")
                                return
                            }

                            imageDownloaded = UIImage(data: data!)

                            let person = Person(name: dictionary["name"] as! String, surname: dictionary["surname"] as! String, tags: [.castana], image: imageDownloaded!)
                            self.storedData.append(person)

                            self.filteredData = self.storedData

                            DispatchQueue.main.sync {
                                UIApplication.shared.endIgnoringInteractionEvents()
                                self.collectionView.reloadData()
                                self.dismiss(animated: false, completion: nil)
                            }

                        }.resume()
                    }
                }
            }) { (error) in
                print("[Error]: \(String(describing: error))")
            }
        }
    }) { (error) in
        print("[Error]: \(error)")
    }

这是我使用的代码,但是这会在仅下载第一张图像后更新我的 UICollectionView,并以此结束 IgnoringInteractionEvents - 并允许用户一次又一次地重新加载数据,这会导致大量图像重复。

从我的数据库中下载每个项目后,如何移动重新加载和 endIgnoringInteractionEvents?

数据库的结构如下:

| folder
-| user
--| autoId
---| name
---| surname
---| imageUrl
--|autoId
---| name
---| surname
---| imageUrl
-| user
--| autoId
---| name
---| surname
---| imageUrl

非常感谢 NicopDev

【问题讨论】:

  • 您的问题是说您正在使用存储 - 这是否意味着 Firebase 存储?如果是这样,你为什么要使用这个URLSession.shared.dataTask(with: url!)?使用Firebase Storage 可以简化代码。此外,您可以创建一个 Dispatch 组并将每个下载添加到该组。当它们都完成后, group.notify 会触发,指示所有任务都已完成。

标签: swift firebase firebase-realtime-database firebase-storage


【解决方案1】:

您将观察者嵌套在嵌套数据上,这似乎是在浪费代码。当您将观察者附加到某个位置时,该位置下的所有数据都已加载。

所以你可以遍历嵌套的快照来获得相同的结果:

newRef.observeSingleEvent(of: .value, with: { (snapshot) in
    for child in snapshot.children {
        let userSnapshot = child as! DataSnapshot
        let userKey = userSnapshot.key

        for child in userSnapshot.children {
            let imageSnapshot = child as! DataSnapshot
            var imageDownloaded: UIImage?
            ...

说完这些,让我们继续讨论您真正的问题:如何检测所有图像何时已加载。

一种简单的跨平台方法是简单地计算您已加载的图像数量,并将其与您知道存在的图像数量进行比较。由于您有一棵仅包含现有图像的树,因此您可以在双嵌套结构的迭代中完成这两项操作

let knownImageCount = 0 // we start with no knowledge of any image
let loadedImageCount = 0 // we also haven't loaded any image yet

for child in snapshot.children {
    let userSnapshot = child as! DataSnapshot
    let userKey = userSnapshot.key

    knownImageCount = knownImageCount + userSnapshot.childrenCount // we've found out about N more images

    for child in userSnapshot.children {
        let imageSnapshot = child as! DataSnapshot
        var imageDownloaded: UIImage?
        ...

        URLSession.shared.dataTask(with: url!) { (data, response, error) in

            ...

            loadedImageCount = loadedImageCount + 1 // we loaded an additional image

            if loadedImageCount == knownImageCount {
                ... // we've loaded all known images, we're done!
            }
        }.resume()

【讨论】:

  • 我现在收到link 这种类型的错误。我做了什么?
  • 这意味着您已经超出了项目的(可能是免费的)配额。我建议搜索错误消息,因为这看起来很相关:google.com/…
  • @Vipera74 难道这个错误也是尝试访问不存在的 url 的结果吗?因此,如果 url 为 nil,例如这里 URLSession.shared.dataTask(with: url!
  • 嘿,杰。您现在收到的错误消息确实是该对象不存在。当我昨天尝试时,超出了配额,并且我在给出的链接中收到了错误消息。这就是为什么最好不要在 Stack Overflow 上使用链接内容的原因之一。 :)
  • 你是对的,我超过了配额,因为我使用的是 PNG 图像而不是 JPEG 压缩,我发送的链接可能是当你超过时 firebase 填充图像链接的方式
猜你喜欢
  • 1970-01-01
  • 2017-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多