Запретить избыточную выборку данных в cellForRow / cellForItem и willDisplayCell - PullRequest
0 голосов
/ 04 марта 2020

У меня есть UICollectionView, чьи ячейки совершают вызовы данных в cellForItemAt:

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellReuseIdentifier, for: indexPath) as? CustomCell
        else { return UICollectionViewCell() }

        cell.viewModel = viewModel.viewModelForCell(at: indexPath.row)
        cell.populate() // this causes the cell's ViewModel to fetch a thumbnail image 
        return cell
    }

Метод populate() заставляет ViewModel ячейки извлечь изображение, чтобы ячейка отображалась в виде эскиза.

Ячейки также могут отменить выборку для этих миниатюр. Например, если пользователь прокручивает ячейку до загрузки ее миниатюры, я отменяю сетевой вызов, начатый в cellForItem. Эта отмена в настоящее время происходит в didEndDisplaying:

    func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        let cellViewModel = viewModel.viewModelForCell(at: indexPath.row)
        cellViewModel.cancelThumbnailFetch()
    }

Это вызывает проблему в следующей ситуации: ячейка, которая активно извлекает изображение, прокручивается за пределы экрана (запускает didEndDisplaying, который отменяет извлечение), затем пользователь прокручивает обратно к ячейке, а затем прокручивает ее достаточно далеко для повторного использования ячейки (что вызвало бы повторный вызов cellForItem для повторного запуска выборки). В этом сценарии выборка никогда не начинается.

Я могу это исправить, позвонив populate() в willDisplayCell:

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        guard let cell = cell as? CustomCell else {
            return
        }
        cell.populate()
    }

Но дважды вызывая populate(), как это каждый раз, когда появляется ячейка (один раз в cellForItem и опять в willDisplayCell) кажется очень неаккуратным. Я всегда могу просто удалить вызов populate() в cellForItem, но тогда я теряю преимущество запуска извлечения как можно скорее. Для справки: миниатюры и их задачи с данными все кэшируются локально, поэтому двойной вызов populate() не вызывает проблем с производительностью (т. Е. Не будет нескольких задач с данными, работающих при загрузке одного и того же эскиза); Меня больше беспокоит чистота кода всего этого

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...