tableview中的图像会再加载几秒钟

时间:2018-09-20 00:39:16

标签: ios swift uitableview tableview

我有一个从Json下载的表格视图中的图像,一切正常,但是在滚动查看相应图像之前,它又加载了几秒钟(这些图像是表中已经可见的图像)。

我的数据结构是:

struct Data: Decodable {
    let name: String
    let img: String
    let phone: String
    let linktaller: String
    let web: String
}

加载图像的单元格的代码为:

             func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {



        guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? AseguradorasTableViewCell else { return UITableViewCell() }



        cell.titleLbl.text = company[indexPath.row].name
        .
        .
        .

         // load image
        if let imageURL = URL(string: company[indexPath.row].img) {
            DispatchQueue.global().async {
                let data = try? Data(contentsOf: imageURL)
                if let data = data {
                    let image = UIImage(data: data)
                    DispatchQueue.main.async {
                        cell.myImage.image = image


                    }
                }
            }

        }

        return cell

 }

加载数据的功能是:

    func downloadJSON() {

        let url = URL(string: "http://myserver.com/data.json")

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

            if error == nil {
                do {
                    self.company = try JSONDecoder().decode([Data].self, from: data!)

                    print(self.company)
                        DispatchQueue.main.async {
                        self.tableView.reloadData()
                        self.refreshControl.endRefreshing()
                    }

                } catch let jsonError{
                    print("error + \(jsonError)")
                }
            }
            }.resume()

   }

查看图片以获取更多详细信息:

image screen

欢迎提出任何解决此问题的建议。

5 个答案:

答案 0 :(得分:2)

enter image description here

在UITableView dequeueReusableCell中-每个UITableViewCell将与不同的数据(图像)一起重复使用几次。 在您的情况下,每个cellForRowAt都会被调用,图像将从服务器加载,因此会有延迟。 解决方案:图像加载完成后,必须在本地应用程序中使用url缓存图像。
(1)-使用SDWebImage-具有缓存支持
(2)-您可以将图像保存在数组中->在cellForRowAt中从该数组加载(如果存在),从服务器加载(如果不存在)

(来自互联网的图片)

答案 1 :(得分:1)

添加以下类以支持缓存图像:

class ImageLoader {

    var cache = NSCache<AnyObject, AnyObject>()

    class var sharedInstance : ImageLoader {
        struct Static {
            static let instance : ImageLoader = ImageLoader()
        }
        return Static.instance
    }

    func imageForUrl(urlString: String, completionHandler:@escaping (_ image: UIImage?, _ url: String) -> ()) {
        let data: NSData? = self.cache.object(forKey: urlString as AnyObject) as? NSData

        if let imageData = data {
            let image = UIImage(data: imageData as Data)
            DispatchQueue.main.async {
                completionHandler(image, urlString)
            }
            return
        }

        let downloadTask: URLSessionDataTask = URLSession.shared.dataTask(with: URL.init(string: urlString)!) { (data, response, error) in
            if error == nil {
                if data != nil {
                    let image = UIImage.init(data: data!)
                    self.cache.setObject(data! as AnyObject, forKey: urlString as AnyObject)
                    DispatchQueue.main.async {
                        completionHandler(image, urlString)
                    }
                }
            } else {
                completionHandler(nil, urlString)
            }
        }
        downloadTask.resume()
    }
}

在单元格中,按以下方式加载图像:

        // Load image
        let fimage = company[indexPath.row].img

        ImageLoader.sharedInstance.imageForUrl(urlString: fimage, completionHandler: { (image, url) in
            if image != nil {

                cell.myImage.image = image

            }
        })

这样,图像下载应该可以正常工作

答案 2 :(得分:0)

由于该单元格何时显示,您可以通过以下方式从互联网下载图像:

let data = try? Data(contentsOf: imageURL)

您应该

  1. 检查imageURL中的图像是否已缓存
  2. 如果已缓存,请从本地加载图像
  3. 如果不缓存,请从Internet下载它,然后缓存它。

或者只是简单地使用SDWebImage或其他任何东西,它将自动为您检查步骤1至3:D

例如,使用SDWebImage

import SDWebImage

imageView.sd_setImage(with: URL(string: "your_image_url"))

答案 3 :(得分:0)

这是经典的单元重用问题。开始下载之前,应在tableView(cellForRowAt:)方法中的每个单元格的图像视图中安装一个占位符图像或nil。这样可以清除之前已安装到单元中的映像,然后异步下载可以在后台运行,并在完成加载后安装映像。

答案 4 :(得分:0)

为解决类似问题,我更改了代码以协调图像的下载与tableView单元格的创建,并将图像存储在本地数组中。

我使用url字符串作为键,创建了一个字典数组来保存下载的图像:

imagesArray = [String:UIImage]()

然后,在代码中每个图像完成下载的位置,将图像添加到数组中,并将新行插入tableView中:

imagesArray.updateValue(UIImage(data:data!)!, forKey:imageURL as!String)

tableView.beginUpdates()

tableView.insertRows(at:[IndexPath(row:imagesArray.count-1,section:0)],其中:.automatic)

tableView.endUpdates()

tableView.reloadData()

我还为每个图像维护一个单独的信息元素数组,包括作为一个元素的图像URL字符串。这使我可以在tableView单元格中显示正确的项目:

cell.itemNameLabel.text = itemRecords [indexPath.row] .itemName
cell.itemImage.image = imagesArray [itemRecords [indexPath.row] .imageURL]

在下载图像时,我展示了进度指示器微调器。

一旦所有图像都下载并加载到imagesArray中,当用户上下滚动查看列出的单元格时,显示就不会出现延迟,并且正确的图像会加载到重复使用的单元格中。