Изображения в виде таблицы загружают еще несколько секунд - PullRequest
0 голосов
/ 20 сентября 2018

У меня есть изображение в виде таблицы, которое загружается с 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 голосов
/ 27 сентября 2018

Чтобы решить подобные проблемы, я изменил свой код, чтобы координировать загрузку изображений с созданием ячеек tableView, хранящих изображения в локальном массиве.

Я создаю словарный массив для хранения загруженных изображений, используя строку URL в качестве ключа:

imagesArray = [String: UIImage] ()

Затем наВ коде, где каждое изображение завершает загрузку, я добавляю изображение в массив и вставляю одну новую строку в tableView:

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

tableView.beginUpdates ()

tableView.insertRows (в: [IndexPath (строка: imagesArray.count-1, раздел: 0)], с: .automatic)

tableView.endUpdates ()

tableView.reloadData ()

Я также поддерживаю отдельный массив информационных элементов для каждого изображения, включая строку URL-адреса изображения как один элемент.Это позволяет мне представить правильные элементы в ячейке tableView:

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

Во время загрузки изображений я представляю счетчик индикатора прогресса.

После того, как все изображения загружены и загружены в массив изображений, НЕТ задержек при представлении, поскольку пользователь прокручивает вверх и вниз для просмотра перечисленных ячеек, и повторно используемые ячейки загружаются с правильными изображениями.

0 голосов
/ 20 сентября 2018

enter image description here

В UITableView dequeueReusableCell - Каждый UITableViewCell будет многократно использоваться с различными данными (изображением).В вашем случае, каждый cellForRowAt вызывается, изображение будет загружено с сервера, поэтому у него будет задержка.Решение: Вы должны кэшировать изображение с помощью URL в локальном приложении, когда загрузка изображения закончится.
(1) - Использовать SDWebImage - с поддержкой кэша
(2) - Вы можете сохранить изображение вмассив -> в cellForRowAt загрузка из этого массива, если он существует, и загрузка с сервера, если он не существует

(изображение из Интернета)

0 голосов
/ 20 сентября 2018

Это классическая проблема повторного использования клеток.Вы должны установить изображение-заполнитель или ноль в представление изображения каждой ячейки в вашем методе tableView(cellForRowAt:) перед началом загрузки.Это очистит предыдущий образ, который был установлен в ячейку, а затем асинхронная загрузка может выполняться в фоновом режиме и установить образ после завершения загрузки.

0 голосов
/ 20 сентября 2018

Добавьте следующий класс для поддержки изображений кэша:

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

            }
        })

При этом загрузка изображений должна работатьправильно

0 голосов
/ 20 сентября 2018

Из-за того, что когда-либо показывается ячейка, вы скачиваете изображение из интернета:

let data = try? Data(contentsOf: imageURL)

Вам следует

  1. Проверить, кэшировано ли изображение в imageURL или нет
  2. Если кэшировано, загрузите изображение из локального
  3. Если не кэшируйте, загрузите его из Интернета, затем кэшируйте его.

Или просто с помощью SDWebImage или что-то еще, он автоматически проверит шаги с 1 по 3 для вас: D

Например, используя SDWebImage

import SDWebImage

imageView.sd_setImage(with: URL(string: "your_image_url"))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...