Why UICollectionView ReloadItems always calls CellForItemAt twice for each item?

896 Views Asked by At

Why UICollectionView ReloadItems always calls CellForItemAt twice for each item? And how to prevent duplicate calls? How to prevent spending double resources for reloading of selected cells? ReloadData() calls CellForItemAt only once. But it's a waste of resources either to reload all rows and sections when only 2-3 items needed to be updated.

The code example may anything with UICollectiionView. For example:

import UIKit

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {

    @IBOutlet weak var collectionView: UICollectionView!

    @IBAction func onTestButton(_ sender: Any) {
        print("test button tapped")
        collectionView.reloadItems(at: [IndexPath(item: 2, section: 0)])
    }

    let reuseIdentifier = "my cell" 
    var items = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]

    override func viewDidLoad() {
        collectionView.delegate = self
        collectionView.dataSource = self
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.items.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! MyCollectionViewCell
        cell.myLabel.text = self.items[indexPath.row]
        cell.backgroundColor = UIColor.cyan
        print("cell for item at \(indexPath.row)")
        return cell
    }
}

When tapping "test button", console output will be:

test button tapped
cell for item at 2
cell for item at 2

But I need to reload "item at 2" only once, and I don't want to reload all items using reloadData().

1

There are 1 best solutions below

4
Duncan C On

You should not make any assumptions about how often the system will call your collectionView(_:cellForItemAt:) method. Just build and return cells when it asks you to. If it sometimes asks you for the same cell twice, just give it the same cell twice.

Collection views and table views ask your to return cells frequently, as the user scrolls. Your collectionView(_:cellForItemAt:) method (or the equivalent table view method) needs to be fast. It shouldn't do network requests, or even decompress JPEG or compressed PNG images from disk unless you cache the results.