Search code examples
swiftuicollectionviewuicollectionviewcellreloading

Refreshing or reloading data on just single object inside a collectionViewCell


i'm trying to update just one single object inside my costumViewCell, i've tried collectionView.reloadItems(at: [IndexPath]), but this method updates my entire cell, which results to a very jittering animations.

here is a sample code of my collectionView cell,

class MyCollectionViewCell: UICollectionViewCell {


    @IBOutlet weak var buttonA: UIButton!
    @IBOutlet weak var buttonB: UIButton!


    var myButtonTitle: String? {
        didSet{
            if let title = myButtonTitle {
                self.buttonA.setTitle(title, for: .normal)
            }
        }
    }

    var buttonActionCallBack: (()->()?)

    override func awakeFromNib() {
        super.awakeFromNib()
        self.animation()

        buttonA.addTarget(self, action: #selector(buttonACallBack), for: .touchUpInside)
    }


    @objc fileprivate func buttonACallBack() {
        self.buttonActionCallBack?()
    }


    fileprivate func animation() {
        UIView.animate(withDuration: 1.0) {
            self.buttonA.transform = CGAffineTransform(translationX: 20, y: 20)
            self.buttonB.transform = CGAffineTransform(translationX: 20, y: 20)
        }
    }
}

here is my DataSource method.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! MyCollectionViewCell

    let item = mainList[indexPath.row]

    collectionView.reloadItems(at: <#T##[IndexPath]#>)
    cell.buttonActionCallBack = {
        () in
        //Do Stuff and Update Just ButtonA Title
    }
    return cell
}

cheers.


Solution

  • The jittering animation occurs because of this collectionView.reloadItems(at: [IndexPath]) line written inside cellForItemAt which is really wrong approach because cellForItemAt called many a times leads to infinite loop of reloading IndexPath's. Instead of that, you just reload only that part which is necessary when action occurs.

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! MyCollectionViewCell
            let item = mainList[indexPath.row]
            //collectionView.reloadItems(at: <#T##[IndexPath]#>) #removed
            cell.buttonActionCallBack = {
                () in
                //Do Stuff and Update Just ButtonA Title
                collectionView.reloadItems(at: [indexPath]) //Update after the change occurs to see the new UI updates
            }
            return cell
        }