首页 > 解决方案 > 如何从 firebase-storage 下载图像以显示在 collectionViewCell 的 Imageview(Swift)中

问题描述

我已将图像上传到 firebase-storage 并将 downloadURL 保存到数据库内的键/值对中。我编写了一个代码,假设在检索到数据后,如果 url 有效,它将在 collectionView 中显示图像。代码在 cellForItemAt 执行,因为包含图片的 collectionView 嵌入在另一个 collectionView 中(将被称为 Main 或 MainCV 以防止混淆)。

为了解决这个问题,我尝试在 MainCV 中重新加载集合视图的数据,并尝试仅使用 ImageView 测试视图控制器上的代码(不成功)。

// function to display images
private func icon(_ imageURL: String) -> UIImage {
        //print("imageURL is \(imageURL)")
        let url = URL(string: imageURL)
        var image: UIImage?
        var imageData:Data?
        if url == nil {
            print("URL is \(imageURL)")
            return #imageLiteral(resourceName: "ic_person_outline_white_2x")
        } else {
            URLSession.shared.dataTask(with: url!) { (data, response, error) in
                if error != nil {
                    print("error")
                    return
                }
                DispatchQueue.main.async {
                    imageData = data
                    image = UIImage(data: imageData!)
                }
                }.resume()
            return image ?? #imageLiteral(resourceName: "ic_person_outline_white_2x")
        }
    }

CellForItemAt 代码块

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! ImageCell
        let imageOption = self.imageData[indexPath.row]
        cell.iconImageView.image = icon(imageOption)
        return cell
        //imageData is an array with empty values that is populated with database values and subsequently reloaded
    }

正如我之前所说,预期的结果是在 collectionView 内显示来自 firebaseStorage 的图像。我的代码不会呈现任何错误,但总是返回默认图像以及打印我确认为我要显示的图像的准确 http 的 imageURl。

标签: swiftuicollectionviewuiimageuicollectionviewcellfirebase-storage

解决方案


你需要学习一些关于异步编程的知识。

您的函数会立即返回,但URLSession.shared.dataTask(with: url!)需要一些时间。时间线:

  1. 图像 = 无
  2. 开始获取数据
  3. 回图??默认图片
  4. 获取数据完成(函数返回后 -> 图像数据丢失)

与其立即返回,不如在函数中提供将图像作为参数的闭包:

private func icon(_ imageURL: String, closure: (UIImage) -> Void)

并将您的代码更新为

URLSession.shared.dataTask(with: url!) { (data, response, error) in
    if error != nil {
        print("error")
        closure(#imageLiteral(resourceName: "ic_person_outline_white_2x"))
    }
    DispatchQueue.main.async {
        imageData = data
        image = UIImage(data: imageData!)
        closure(image)
    }
}.resume()

闭包本身可以是一个接受图像作为参数并将此图像异步设置到您的集合视图单元格的函数

此外,您希望在加载图像之前提供一些默认或加载图像。或者使用 ActivityIndi​​cator。

希望这可以帮助!


推荐阅读