Обновление высоты ячейки после загрузки изображения

я показываю текст и изображения в UITableView. Сначала загружается изображение. Поскольку до загрузки изображения я не знаю размер изображения, поэтому я изначально поставил UIImageView некоторого фиксированного размера. И когда изображение загружается, я изменяю размер UIImageView.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

// Download image

    dispatch_async(dispatch_get_main_queue(), ^{

    // UIImageView resizing  
    });  
});

все это происходит в cellForRowAtIndexPath.
Проблемы, с которыми я сталкиваюсь здесь:
1. Как обновить высоту ячейки ? Учитывая, что в одной ячейке может быть много изображений. Так что мне нужно чтобы изменить положение нижнего изображения, когда выше одной загрузки.
2. Я пробовал использовать UITableView beginUpdates и endUpdates, но это прокручивается в верхней части клетки дает плохой пользовательский опыт.

это, как интерфейс выглядит, как на reloadData. Есть 5 изображений для загрузки:пользовательский интерфейс после UITableView reloadData

1 ответов


Короткий Ответ:

  • дайте достаточно передышки estimatedRowHeight
  • изменение UITableViewCell после возвращения в dequeueReusableCellWithIdentifier будет не работа с кэшированными клеток
  • вызвать перезагрузку одной ячейки с reloadRowsAtIndexPaths
  • управление кэша с основными данными и пусть NSFetchedResultsController шаблонный код может выполнять всю работу пользовательского интерфейса.

Подробнее

нет неожиданной прокрутки, только обновляет изображения как они приходят:

  1. если ячейка обновляется at или ниже на горизонте UITableView будет не свиток
  2. если ячейка обновляется выше сверху,UITableView будет не свиток
  3. the UITableView будет прокручиваться только тогда, когда ячейка находится на виду,и требует больше места, чем доступный.

пусть UITableViewAutomaticDimension сделать тяжелую работу

вам нужно сказать Cocoa Touch, что ячейка несвежий, так что это вызовет новая dequeueReusableCellWithIdentifier, к которому вы собираетесь вернуться ячейка с правильной высоте.
За исключением перезагрузки всего представления таблицы или одного из его разделов и предположения, что ваши индексы стабильны, invoke -tableView:reloadRows:at:with: передача indexPath ячейки, которая просто изменилось, и .fade анимация.

код:

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.estimatedRowHeight = 250 // match your tallest cell
    tableView.rowHeight = UITableViewAutomaticDimension
}

использовать URLSession. Когда изображение становится доступным, огонь reloadRows:at:with:

func loadImage(_ url: URL, indexPath: IndexPath) {
    let downloadTask:URLSessionDownloadTask =
        URLSession.shared.downloadTask(with: url, completionHandler: {
        (location: URL?, response: URLResponse?, error: Error?) -> Void in
        if let location = location {
            if let data:Data = try? Data(contentsOf: location) {
                if let image:UIImage = UIImage(data: data) {
                    self.cachedImages[indexPath.row] = image // Save into the cache
                    DispatchQueue.main.async(execute: { () -> Void in
                        self.tableView.beginUpdates()
                        self.tableView.reloadRows(
                            at: [indexPath],
                            with: .fade)
                        self.tableView.endUpdates()
                    })
                }
            }
        }
    })
    downloadTask.resume()
}

раз в кэше, cellForRow просто читает в него из потока пользовательского интерфейса:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    let cell = tableView.dequeueReusableCell(withIdentifier: "id") as! CustomCell
    cell.imageView.image = cachedImages[indexPath.row]      // Read from the cache
    return cell
}

пример: получить случайный набор изображений из * Wikipedia*

Xcode demo

► найти это решение на GitHub и дополнительные сведения о Swift Рецепты.