代码之家  ›  专栏  ›  技术社区  ›  Mario Burga

tableview中的图像加载另一个图像几秒钟

  •  1
  • Mario Burga  · 技术社区  · 6 年前

    我在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 回复  |  直到 6 年前
        1
  •  1
  •   AlbertB    6 年前

    为缓存映像支持添加以下类:

    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
  •  2
  •   Nguyen Hoan    6 年前

    enter image description here

    在UITableView中 dequeueReusableCell -每个UITableViewCell将使用不同的数据(图像)重复使用几次。 cellForRowAt 调用时,将从服务器加载映像,因此会有延迟。 解决方案:当图像加载完成时,必须在本地应用程序中使用url缓存图像。
    (1) -使用 SDWebImage
    (2) -可以将图像保存在数组中->在里面 cellForRowAt公司 如果存在,则从此数组加载;如果不存在,则从服务器加载

        3
  •  0
  •   Quoc Nguyen Nofan Munawar    6 年前

    因为每当手机显示时,你都可以通过

    let data = try? Data(contentsOf: imageURL)
    

    你应该

    1. imageURL 是否已缓存
    2. 如果已缓存,则从本地加载图像

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

    例如,使用SDWebImage

    import SDWebImage
    
    imageView.sd_setImage(with: URL(string: "your_image_url"))
    
        4
  •  0
  •   Duncan C    6 年前

    tableView(cellForRowAt:)

        5
  •  0
  •   AndyW58    6 年前

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

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



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

    imagesArray.updateValue(UIImage(data:data!)!,forKey:imageURL为!(字符串)



    tableView.insertRows(位于:[IndexPath(行:imagesArray.count-1,节:0)],带:。自动)



    tableView.reloadData()

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

    cell.itemNameLabel.text=itemRecords[indexPath.row].itemName


    在下载图像时,我提供了一个进度指示器微调器。

    一旦图像全部下载并加载到imagesArray中,当用户上下滚动以查看列出的单元格时,就不会延迟显示,并且重用的单元格将加载正确的图像。