UICollectionView будет воссоздавать ячейки при вызове метода "reloadItems" - PullRequest
0 голосов
/ 09 ноября 2018

В моей ячейке есть изображение, которое загружается из сети, поэтому мне нужно установить высоту ячейки как динамическую. Когда загрузка изображения закончится, я позвоню self.collectionView.reloadItems(at: [indexPath]), чтобы вызвать метод делегата для установки новой высоты.

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

enter image description here

Как я могу решить эту проблему? Это ошибка на UICollectionView от Apple или что-то не так я сделал?

Весь код:

// code from ViewController
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: AnnounmentWallCollectionViewCell.cellIdentifier, for: indexPath) as! AnnounmentWallCollectionViewCell

    let announcement = announcements[indexPath.row]
    cell.collectionView = collectionView
    cell.setBanner(from: announcement.banner, indexPath: indexPath, completion: { [unowned self] (height) in
        self.bannersHeight[indexPath.row] = height
    })
    cell.setHTMLContent(announcement.content)
    contentsHeight[indexPath.row] = cell.htmlContentSize.height
    printD("indexPath: \(indexPath)")
    return cell
}

// code from cell
func setBanner(from url: URL?, indexPath: IndexPath, completion: @escaping (_ height: CGFloat)->()) {
    // URL(string: "https://i.imgur.com/qzY7BJ9.jpg")
    if let url = url {
        if let banner = SDImageCache.shared().imageFromDiskCache(forKey: url.absoluteString) {
            self.bannerView.isHidden = false
            self.bannerView.image = banner.scaleWidth(to: self.bounds.width - 32) // leading + trailling
            self.bannerHeight.constant = self.bannerView.image?.size.height ?? 1
            completion(self.bannerHeight.constant)
            printD("NO Download: \(indexPath)")
            let animationsEnabled = UIView.areAnimationsEnabled
            UIView.setAnimationsEnabled(false)
            self.collectionView.reloadItems(at: [indexPath])
            UIView.setAnimationsEnabled(animationsEnabled)
        } else {
            DispatchQueue.global().async {
                SDWebImageDownloader.shared().downloadImage(with: url, options: .useNSURLCache, progress: nil) { (banner, data, error, finished) in
                    DispatchQueue.main.async {
                        if let banner = banner {
                            SDImageCache.shared().store(banner, forKey: url.absoluteString, toDisk: true)
                            self.bannerView.isHidden = false
                            self.bannerHeight.constant = banner.scaleWidth(to: self.bounds.width - 32)?.size.height ?? 1
                            completion(self.bannerHeight.constant)
                            self.collectionView.reloadData()
                            printD("Download: \(indexPath): \(self.bannerHeight.constant)")
                        } else {
                            self.bannerView.isHidden = true
                            self.bannerHeight.constant = 1
                            completion(self.bannerHeight.constant)
                        }
                    }
                }
            }
        }
    } else {
        bannerView.isHidden = true
        bannerHeight.constant = 1
        completion(bannerHeight.constant)
    }
}

// code from delegate 
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let width = self.view.bounds.width
    let height = bannersHeight[indexPath.row] + contentsHeight[indexPath.row]
        + 1 // sticker
        + 11 // banner top
    printD("indexPath: \(indexPath): \(height)")
    return CGSize(width: width, height: height)
}

1 Ответ

0 голосов
/ 09 ноября 2018

Это не ошибка. Вот так вы перезагрузите ячейку для заданного пути индекса. Если вы хотите обновить макет, попробуйте

[self.collectionView.collectionViewLayout invalidateLayout]

вместо

self.collectionView.reloadItems(at: [indexPath])

и затем верните правильный размер в методе делегата.

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return //whatever size that you want to return. 

}

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

...