UICollectionView cells are displayed only after the second call to reloadData

I probably do something incredibly stupid, but I can’t understand what is happening with my life ...

What I'm trying to do is pretty simple. I have UICollectionView, depending on the data that I download from the server. After receiving and installing data from the server, I call it reloadData()as a collection. When I do this, it numberOfItemsInSectionis called with the correct count, but it is cellForItemAtnever called unless I call reloadData()the second time (I don’t even need to delay it).

Here is a general idea (although I understand that this is probably due to some arrangement in another place, but perhaps this will be enough to start the conversation):

class MyViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

    @IBOutlet weak var collectionView: UICollectionView!

    var data = [DataModel]()

    override func viewDidLoad() {
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.register(UINib(nibName: "MyCell", bundle: nil), forCellWithReuseIdentifier: "MyCell")
        getData()
    }

    func getData() {
        someAsyncMethodToGetData() { (data) in
            // Using CloudKit so I think this is necessary, but tried it with and without
            DispatchQueue.main.async {
                self.data = data
                self.collectionView.reloadData()
                // This is the only way to get cells to render and for cellForItemAt to be called after data is loaded
                self.collectionView.reloadData()
            }
        }

    // Gets called initially AND after reloadData is called in the data completion closure. First time is 0, next time is number of DataModel objects
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return data.count
    }

    // Only gets called initially (unless I call reloadData() twice)
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = feedCollectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as? MyCell else {
            return UICollectionViewCell()
        }

        // Configure the cell with data...

        return cell
    }
}

So, here are some things I've already tried:

  • reloadData() ( ​​ Thread.isMainThread )
  • reloadData() , - - , .
  • performBatchUpdates SO, .
  • setNeedsLayout setNeedsDisplay ( , , .

? 🙏

1

, , , . reloadData, . , 1 getData(). getData() reloadData(), 1 ( 10 , 1 1). , , reloadData() , , , . , reloadData() , ? 🤔

, , " " .

+6
1

, UICollectionViewFlowLayout . , collectionView.contentSize . -

self.collectionView.reloadData()
self.collectionView.collectionViewLayout.invalidateLayout()

, .

+6

Source: https://habr.com/ru/post/1015878/


All Articles