1

When calling performBatchUpdates on a horizontal scroll UICollectionView which has an contentOffset.x > 0, it executes a rather weird animation.

I recreated the error with a sample cell which shows exactly the error we get in our app. This happens also when there are no changes to be performed in performBatchUpdates at all. After completion, the items in the UICollectionView are correct, so it is just an animation problem.

Example GIF of behaviour

Did anybody face that issue already and has a solution for this?

My ViewController.swift:

class CollectionViewCell: UICollectionViewCell {
    @IBOutlet var label: UILabel!
}

class ViewController: UIViewController {
    @IBOutlet private var collectionView: UICollectionView!
    
    private var items: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let layout = UICollectionViewFlowLayout()
        layout.estimatedItemSize = CGSize(width: 1, height: 1)
        layout.scrollDirection = .horizontal
        
        collectionView.collectionViewLayout = layout
        collectionView.dataSource = self
        collectionView.delegate = self
        collectionView.contentInset = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)
        collectionView.showsHorizontalScrollIndicator = false
    }
}

extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        items.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? CollectionViewCell
        
        cell?.label.text = items[indexPath.row].description
        
        return cell ?? UICollectionViewCell()
    }
}

extension ViewController: UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        items.remove(at: indexPath.row)
        
        collectionView.performBatchUpdates({
            self.collectionView.deleteItems(at: [indexPath])
        }, completion: nil)
    }
}

Download example project here: https://wetransfer.com/downloads/74454a6b9df114529ba3a26b7b9488ab20200720141429/05eb4d

Dennis Kozevnikoff
  • 2,078
  • 3
  • 19
  • 29
fgroeger
  • 422
  • 5
  • 18
  • I downloaded your project and ran it, and the first thing that happened is that a hundred serious warnings were dumped into the console. There is absolutely no point proceeding until you fix those. Your cell estimated sizes and autolayout constraints are being managed incorrectly. – matt Jul 20 '20 at 14:44

1 Answers1

0

You have to set itemSize for you collectionView cell:

layout.itemSize = CGSize(width: 44, height: 44)

instead of(or in addition):

layout.estimatedItemSize = CGSize(width: 1, height: 1)

More about estimated and when you needed:
https://developer.apple.com/documentation/uikit/uicollectionviewflowlayout/1617709-estimateditemsize

And itemSize:
https://developer.apple.com/documentation/uikit/uicollectionviewflowlayout/1617711-itemsize

You are welcome!

vpoltave
  • 1,612
  • 3
  • 14
  • 31
  • I want to use automatic sizing instead of fixed item sizes. Every item has a different width. Using `layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize` doesn't work either. – fgroeger Jul 20 '20 at 14:37
  • @fgroeger If you do what this answer suggests, does the problem in fact go away? – matt Jul 20 '20 at 14:39
  • When i set fixed item sizes, it works, yes! But that is not an option, since every item has a different width. – fgroeger Jul 20 '20 at 14:40
  • 1
    @fgroeger But the problem is that you are managing self-sizing cells incorrectly. Whether fixed size is correct or not, if this answer fixes the issue, you need to take that fact into account. – matt Jul 20 '20 at 14:45
  • But it can't be a solution not just to use self sizing cells, why does it exists then? – fgroeger Jul 20 '20 at 14:50
  • @fgroeger I didn't say you can't use self sizing cells. I said you need to use them correctly. As I have explained [elsewhere](https://stackoverflow.com/a/52428617/341994), I _also_ contend that automatic self sizing cells for a flow layout is not actually a thing. But you can certainly use variable-width cells if you do it correctly. – matt Jul 20 '20 at 14:59