Swift 3:tableView从Firebase复制加载的图像 [英] Swift 3 : tableView duplicating loaded images from Firebase

查看:96
本文介绍了Swift 3:tableView从Firebase复制加载的图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试显示带有图片的用户列表。这是代码

I am trying to show a user list with images. Here is the code

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! UserListTableViewCell
    let message = messages[indexPath.row]
    cell.message = message
    return cell
}

在UserListTableViewCell文件中,我正在下载图像(也使用缓存)并在桌面上显示它。但我发现有些行有重复/重复的图像。重新加载后重复消失,但它的背面垂直滚动。

In the UserListTableViewCell file, I am downloading the images ( also using cache) and showing it on the table. But I see that some of the rows have duplicated/repeated image. Upon reloading the duplicates disappear, but its back on vertical scrolling.

发生这种情况:

这是UserListTableViewCell文件:

Here is the UserListTableViewCell file :

import UIKit
import Firebase

class UserListTableViewCell: UITableViewCell {

@IBOutlet weak var username: UILabel!
@IBOutlet weak var textMessage: UILabel!
@IBOutlet weak var timeLabel: UILabel!
@IBOutlet weak var userImage: UIImageView!



var message: Message? {

    didSet {

        if let id = message?.chatPartnerID() {

            let database = Database.database().reference()
            let ref = database.child("Users").child(id)
            ref.observeSingleEvent(of: .value, with: {
                (snapshot) in

                if let dictionary = snapshot.value as? [String: AnyObject] {


                        self.username.text = dictionary["username"] as? String

                        if let profileImageUrl = dictionary["image"] as? String, profileImageUrl != "" {
                                                            self.userImage.image = UIImage(named: "blank-user")
                            self.userImage.loadImageFromCacheWithUrlString(urlString: profileImageUrl)
                            self.userImage.layer.cornerRadius = self.userImage.frame.size.width/2
                            self.userImage.clipsToBounds = true

                        } else {

                            self.userImage.image = UIImage(named: "blank-user")
                            self.userImage.layer.cornerRadius = self.userImage.frame.size.width/2
                            self.userImage.clipsToBounds = true
                        }

                }



            }, withCancel: nil)
        }


        textMessage.text = (message?.text)! + " " + (message?.chatPartnerID())!

        if let seconds = message?.timestamp?.doubleValue {
            let timestampDate = Date(timeIntervalSince1970: seconds)

            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "hh:mm a"
            timeLabel.text = dateFormatter.string(from: timestampDate)
        }


        //userImage.image = message?.
    }
} }

图片下载扩展文件:

extension UIImageView {
func loadImageFromCacheWithUrlString( urlString: String) {

    if urlString != "" {
        self.image = nil

        if let cachedImage = imageCache.object(forKey: urlString as AnyObject) {

            self.image = cachedImage as? UIImage
            self.contentMode = .scaleAspectFill
            return
        }


        let url = URL(string : urlString )

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

            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
                    self.contentMode = .scaleAspectFill
                }


            })

        }).resume()
    }


}

}

推荐答案

其他解决方案

你可以使用 UIImage(数据:data(contentsOf:URL(string:urlString)!))从url中检索图像,但它占用主线程,因此需要缓存。
此解决方案不显示错误图像但不好,因为初始化导致延迟。

You can use UIImage(data: Data(contentsOf: URL(string: urlString)!)) to retrieve image from url, but it occupies the main thread, so cache is neccesary. This solution would not display error image but not good because initialize cause delay.

class URLImageRetriever {
    fileprivate static var cache = NSCache<AnyObject,UIImage>()
    static func getImage(from urlString: String) -> UIImage? {
        var image = URLImageRetriever.cache.object(forKey: urlString as AnyObject)
        if image == nil {
            do {
                try image = UIImage(data: Data(contentsOf: URL(string: urlString)!))
                if let image = image {
                    Designer.cache.setObject(image, forKey: urlString as AnyObject)
                }
            } catch {

            }
        }
        return image
    }
}

来源

您的扩展程序 loadImageFromCacheWithUrlString 可能不会适合这种情况。

Your extension loadImageFromCacheWithUrlString might not suitable for this situation.

我们来讨论这种情况:


  1. 你的ImageView a 被要求提供 url-a 的图像。现在有一个URLSession 任务-a 正在运行。

  2. 你的UITableViewCell被重用来呈现另一个数据源,所以你的ImageView a 要求提供 url-b 的图像。现在有一个URLSession 任务-b 正在运行。

  3. task-b url-b 中检索图片。您的ImageView a 现在可以完美地显示来自 url-b 的图片。

  4. tast -a 稍后的tetrieved图片。您的ImageView设置为显示图像格式 url -a 。让我们感到困惑。

  1. Your ImageView a requested to present image of url-a. Now there is a URLSession task-a running.
  2. Your UITableViewCell are reused to present another datasource, so your ImageView a requested to present image of url-b. Now there is a URLSession task-b running.
  3. task-b retrieved picture from url-b. Your ImageView a now display image from url-b perfectly.
  4. tast-a tetrieved picture later. Your ImageView be set to display image form url-a. And make us confused.

每当你检索图片时,你应该检查你想要用imageview显示的内容。

You should check what you want to display with your imageview whenever you retrieve picture.

ex:

URLImageUtil.loadImageFromCacheWithUrlString(urlString: profileImageUrl, completion: {
    url, image in
    if self.message.profileImageUrl == url {
        self.userImage.image = image
    }
})
class URLImageUtil {
    static func loadImageFromCacheWithUrlString(urlString: String, completion: @escaping (_ url: URL,_ image: UIImage)->Void) {
        if let url = URL(string: urlString) {
            URLSession.shared.dataTask(
                with: url, completionHandler: {data,response,error in
                    if (data) != nil {
                        if let image = UIImage.init(data: data!) {
                            completion(url, image)
                        } else {
                            print("data not image from url: \(url)")
                        }
                    } else {
                        print("no data from url: \(url)")
                    }
            })
        } else {
            print("error url: \(urlString)")
        }
    }
}

这篇关于Swift 3:tableView从Firebase复制加载的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆