Ячейки перекрываются в UICollectionView

Я показываю результаты веб-запроса к пользовательскому API в UICollectionView с ячейками динамического размера. Однако, когда я вызываю reloadSections после извлечения данных, многие ячейки отображаются перекрывающимися.

перекрываются ячейки

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

Я отследил ошибку вызова reloadSections в блоке завершения для моего веб-запроса. Используя жестко закодированный текст, представление коллекции правильно отображается с исходным макетом. Если reloadSections вызывается в блоке завершения, возникает ошибка. Ниже приведен соответствующий код:

override func viewDidLoad() {
    super.viewDidLoad()

    collectionView.register(UINib.init(nibName: "ExhibitionsCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "ExhibitionsCollectionViewCell")
    layout.estimatedItemSize = CGSize(width: 1, height: 1)

    collectionView.dataSource = exhibitionsDataSource
    collectionView.delegate = self

    store.fetchExhibitions {
        (exhibitionsResult) -> Void in

        switch exhibitionsResult {
        case let .success(exhibitions):
            print("Successfully found \(exhibitions.count) exhibitions.")
            if exhibitions.first != nil {
                self.exhibitionsDataSource.exhibitions = exhibitions
            }
        case let .failure(error):
            print("Error fetching exhibitions: \(error)")
            self.exhibitionsDataSource.exhibitions.removeAll()
        }
        // this is the line that produces the erroneous layout
        self.collectionView.reloadSections(IndexSet(integer: 0))
    }

}

Код, выполняющий веб-запрос:

func fetchExhibitions(completion: @escaping (ExhibitionsResult) -> Void) {

    let url = WebAPI.exhibitionsURL
    let request = URLRequest(url: url)
    let task = session.dataTask(with: request) {
        (data, response, error) -> Void in

        let result = self.processExhibitionsRequest(data: data, error: error)
        OperationQueue.main.addOperation {
            completion(result)
        }

    }

    task.resume()
}

Если есть какой-либо другой код, который был бы полезен для ответа на этот вопрос, дайте мне знать.

Обновление: я исправил проблему, реализовав следующий метод делегата UICollectionViewDelegateFlowLayout.

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    let cell = collectionView.cellForItem(at: indexPath)
    let height = cell?.contentView.bounds.height ?? 1
    let width = cell?.contentView.bounds.width ?? 1


    return CGSize(width: width, height: height)
}

Update2: после замены моих поддельных данных Lorem Ipsum на данные, фактически полученные с сервера, проблема возникла снова. Однако мне удалось окончательно решить проблему, просто переключив линию

self.collectionView.reloadSections(IndexSet(integer: 0))

to

self.reloadData()

Я бы подумал, что reloadSection(_:) просто выполняет то же действие, что и reloadData(), но для выбранных разделов и в документации, похоже, не указано иное... но в любом случае теперь это работает!


person L Christiansen    schedule 09.03.2018    source источник
comment
Тщательно пройдитесь буквально всем, что влияет на размер. Ячейка xib, макет потока, контейнер Xib, ширина/высота, вставки по краям. Если это не так, ознакомьтесь с функциями очереди и повторного использования PrepareForReuse(). Автомакет факта рассчитывается непосредственно перед размещением. Тайминги анимации (0,25 секунды по умолчанию). Размер Xibs в XCode по сравнению с различиями в телефоне (по-разному ли он выглядит на разных размерах телефона / планшета)? Все они дадут вам рекомендации о том, где это сузить.   -  person Stephen J    schedule 09.03.2018


Ответы (1)


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

Сосредоточьтесь на функции

сайзфоритематиндекспас

Пример:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
        return CGSizeMake(320, 500);
    }
person Pedro Carrasco    schedule 09.03.2018
comment
Похоже, это решает мою проблему! Я предполагал, что, поскольку я использую автомакет и ячейки с автоматическим изменением размера, мне не нужно будет реализовывать этот метод, но это предположение кажется неверным. - person L Christiansen; 20.03.2018
comment
Хотя это действительно решило мою первоначальную проблему, в конечном итоге это не решило проблему. Мне пришлось изменить функцию для перезагрузки данных после их получения с сервера. - person L Christiansen; 20.03.2018