从Firebase Swift加载后,单元格未显示图像

时间:2018-05-25 03:39:49

标签: ios swift firebase uicollectionviewcell firebase-storage

我有一个显示图像或文本的UITableViewCell。我已将我的UIImageView高度和宽度设置为< = 150,以便在图像不存在但文本为的情况下不会影响单元格高度。 (这是一个消息应用程序)

现在我的问题是,单元格在加载后没有显示图像,用户需要返回,并再次查看此屏幕以查看图像。我该怎么解决这个问题?

在加载图片之前:

enter image description here

成功加载图片后

enter image description here

你可以看到,它没有显示,只有视图被扩展

如果用户按下BACK并在此视图中再次显示,

enter image description here

现在显示的图像。

我该如何解决这个问题?因为我无法在tableviewcell中编写tableview.reloaddata()

我的tableviewcell中的代码用于配置我的单元格:

func configCell(message: Message) {

    self.message = message

    if message.fromId == currentUser {

        sentView.isHidden = false

        sentMsgLabel.text = message.textMessages

        receivedMsgLabel.text = ""

        receivedView.isHidden = true

        timeReceived.text = ""

        timeSent.text = message.timestamp

        youLabel.text = "You"

        themLabel.text = ""


        if let ImageUrl = message.imageUrlLink {

            self.receivedimg.loadImageUsingCacheWithUrlString(ImageUrl)
        }
        }

        else {

        sentView.isHidden = true

        sentMsgLabel.text = ""

        receivedMsgLabel.text = message.textMessages

        receivedMsgLabel.isHidden = false

        timeReceived.text = message.timestamp

        timeSent.text = ""

        // setting name for receipient
        Database.database().reference().child("users").child(message.fromId!).child("name").observe(.value) { (datasnapshot) in
        if let name = datasnapshot.value as? String {
                self.themLabel.text = name
            }
        }

        youLabel.text = ""
    }
}

我的loadImageUsingCacheWithUrlString代码将是一个扩展名如下:

let imageCache = NSCache<AnyObject, AnyObject>()

    extension UIImageView {

    func loadImageUsingCacheWithUrlString(_ urlString: String) {

        self.image = nil

        //check cache for image first
        if let cachedImage = imageCache.object(forKey: urlString as AnyObject) as? UIImage {
            self.image = cachedImage
            return
        }

        //otherwise fire off a new download
        let url = URL(string: urlString)
        URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in

            //download hit an error so lets return out
            if error != nil {
                print(error ?? "")
                return
            }

            DispatchQueue.main.async(execute: {

                if let downloadedImage = UIImage(data: data!) {
                    imageCache.setObject(downloadedImage, forKey: urlString as AnyObject)

                    self.image = downloadedImage
                }
            })

        }).resume()
    }

}

5 个答案:

答案 0 :(得分:1)

下载图片后您的问题清楚,您的单元格没有及时更新,请在单元格内尝试 self.setNeedDisplays()。它告诉您的单元格应该在下一个视图周期中更新。

我建议使用KingFisher框架,而不是加载和捕获自己,它几乎可以处理来自远程服务器的图像:下载,捕获,预取......以及下载后立即显示您的图像

答案 1 :(得分:1)

我尝试了很多方法,最后..在我的ViewDidload中,我只是添加了延迟

 DispatchQueue.main.asyncAfter(deadline: .now() + 1){
        self.tableView.reloadData()
    }

需要延迟。没有它,它就无法运作。我假设它是由于在图像加载完成之前设置并加载了单元格高度,所以表格单元不知道需要多少高度,这就是为什么我们需要重新加载tableview之后1秒延迟

答案 2 :(得分:0)

而不是对UITableViewCell

中的cellForRowAt执行操作执行操作
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //Your actuions here
}

然后,您可以在tableView.reloadData()

中使用UITableViewController

希望这有助于解决您的问题。

答案 3 :(得分:0)

似乎这个代码正在执行一次,但是你的UITableView仍在加载单元格,因为计数显然是2.当你将Message对象传递到UICollectionViewCell类内cellForRowAt indexPath类时1}}方法,您将要对该消息使用didSet,然后调用您的函数。这意味着每次传入消息时以及传入消息时,都会执行didSet内部的任何内容。

在UICollectionViewCell类中:

var message: Message? {
    didSet {
        configCell(message)
    }
}
使用您的UITableViewController

类:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = // your cell here dequeue cell and downcast as your cell class e.g as! MyCell

    cell.message = yourMessagesArray[indexPath.row]

    return cell
}

答案 4 :(得分:0)

我遇到了同样的问题,这就是我解决的方法。

ViewController 内创建一个函数,该函数将动态更新每个单元格

private func reloadRowAt(_ indexPath: IndexPath) {
    self.tableView.beginUpdates()
    self.tableView.reloadRows( at: [indexPath], with: .fade)
    self.tableView.endUpdates()
}

现在在 cellForRowAtindexPath()内部使用它:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: identifier) as? MyCustomCell else { return UITableViewCell()}

   // Download and refresh cell
   let image = imageDownloader.loadImage(from: url) {
       self.reloadRowAt(indexPath) 
   }
   cell.image = image
   return cell
  }

现在在代码{ self.reloadRowAt(indexPath) }中查找,这是下载图像的方法的完成处理程序,一旦下载了图像,它将返回到单元格。

func loadImage(from url: URL, completion: @escaping () -> Void ) -> UIImage {
    let size = CGSize(width: 100, height: 140)
    // Download and Compress image to fit container size
    DispatchQueue.global(qos: .background).async {
      guard let newimage = self.downloadAndCompress(url: url, newSize: size) else { return }
      // Show in UI
      DispatchQueue.main.async {
        completion()
      }
    }
    return UIImage()
  }

此外,我使用方法self.downloadAndCompress将下载的图像压缩为新的大小。

查看完整代码:

https://gist.github.com/richimf/fad8d320fbfb5059c5472e0f55ea24c2