UICollectionView.reloadItems(at:) is broken. Causes strange reloading of the same cell multiple times for different index paths.

Originator:servidionicholas
Number:rdar://FB7631286 Date Originated:2020-03-18
Status:Open Resolved:
Product:UIKit Product Version:iOS 13
Classification:Unexpected Behavior Reproducible:100%
 
UICollectionView.reloadItems(at:) is broken. Causes strange reloading of the same cell multiple times for different index paths.

iPhone Pro Max Simulator
Xcode 11.3
macOS 10.14.4

Steps to repro:
1. Run the attached project on iPhone 11 Pro Max Simulator.
2. We call `self.collectionView.reloadItems(at: [IndexPath(item: 2, section: 0)])`

Expected: Only a single index path is reloaded.

Actual: 4 index paths are reloaded.
```
<CollectionViewMayhem.FooCell: 0x7fe7f5606e10; baseClass = UICollectionViewCell; frame = (60.6667 0; 50 50); layer = <CALayer: 0x600001b488e0>>, [0, 1]
<CollectionViewMayhem.FooCell: 0x7fe7f5606e10; baseClass = UICollectionViewCell; frame = (0 0; 50 50); hidden = YES; layer = <CALayer: 0x600001b488e0>>, [0, 0]
<CollectionViewMayhem.FooCell: 0x7fe7f5606e10; baseClass = UICollectionViewCell; frame = (121.333 0; 50 50); hidden = YES; layer = <CALayer: 0x600001b488e0>>, [0, 2]
<CollectionViewMayhem.FooCell: 0x7fe7f5606e10; baseClass = UICollectionViewCell; frame = (121.333 0; 50 50); hidden = YES; layer = <CALayer: 0x600001b488e0>>, [0, 2]
```

The workaround is to just use `reloadData()` but that's not ideal.

Please let me know if you have any questions. Thanks!

Here's the sample code:

++++++++++

import UIKit

class FooCell: UICollectionViewCell {}

class ViewController: UIViewController, UICollectionViewDataSource {

    @IBOutlet var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.register(FooCell.self, forCellWithReuseIdentifier: "Foo")
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            print("Reloading")
            self.collectionView.reloadItems(at: [IndexPath(item: 2, section: 0)])
        }
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 3
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Foo", for: indexPath)
        print("\(cell), \(indexPath)")
        return cell
    }
}

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!