Alwin Vazhappilly
Alwin Vazhappilly

Reputation: 1514

CollectionView indexPath not updating after delete an item from it using swift

Actually I develop a Wishlist page for an e-comerce app. The Wishlist cell contains a Love(Wishlist) button.

Requirement

  1. Delete cell when I tap on Love(Wishlist) button
  2. nice deletion animation

enter image description here

WishCell - button click part

class WishCell: UICollectionViewCell {

    var wishButtonTapped : (() -> Void)? = nil

    @IBAction func wishBtnTapped(_ sender: Any) {
        if let wishBtnTap = wishButtonTapped {
            wishBtnTap()
        }
    }
}

CollectionView CellForRowAt

Button click is handled in CellForRowAt.

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

            cell.configureCell(wishlist: wishlists[indexPath.row])

            // Wish Button
            cell.wishButtonTapped = {
                print("indexPath", indexPath)
                print("indexPathRow", indexPath.row, wishlistJSON.count)

//                wishlistJSON.remove(at: indexPath.row)
//                self.parseWishlistJSON()
                self.wishlists.remove(at: indexPath.row)
                collectionView.deleteItems(at: [indexPath])
//                self.collectionView.reloadData()
                self.updateDesign()
            }
            return cell

        } else {
            return UICollectionViewCell()
        }
    }

Print Log

tap on third cell

indexPath [0, 2]
indexPathRow 2 5

tap again on third cell

indexPath [0, 3]
indexPathRow 3 5

Problem

  1. IndexPath of collectionView is not updating after delete the cell
  2. Crash the app at wishlistJSON.remove(at: indexPath.row) because the array indexOutOfBound

Upvotes: 3

Views: 1882

Answers (3)

Steve B
Steve B

Reputation: 600

I had the same issue and for me, forcing a collectionView.reloadData() did the trick. Still unclear why the deletion of a row doesn't update the IndexPath for the cells...but at least this got it working

Upvotes: 1

Vinaykrishnan
Vinaykrishnan

Reputation: 768

Reloading the Collection-view must do the trick

[self.collectionView performBatchUpdates:^{
    [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
} 

Upvotes: 0

Alwin Vazhappilly
Alwin Vazhappilly

Reputation: 1514

When cells get reused, cell.wishButtonTapped actions will get added again! That's not what we want.

Protocols Approach solve this

protocol WishlistDelegate: class {
    func wishlistBtnTap(_ sender: WishCell)
}

WishCell

class WishCell: UICollectionViewCell {

    weak var delegate: WishlistDelegate?
    
    @IBAction func wishBtnTapped(_ sender: Any) {
        delegate?.wishlistBtnTap(self)
    }

CollectionView CellForRowAt

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "WishCell", for: indexPath) as? WishCell {
            
            cell.configureCell(wishlist: wishlists[indexPath.row])
            cell.delegate = self
        
            return cell
            
        } else {
            return UICollectionViewCell()
        }
    }

extension - WishlistDelegate

extension WishlistVC: WishlistDelegate {
    func wishlistBtnTap(_ sender: WishCell) {
        guard let tappedIndexPath = collectionView.indexPath(for: sender) else { return }
        
        // Delete the Item
        wishlists.remove(at: tappedIndexPath.row)
        collectionView.deleteItems(at: [tappedIndexPath])
    }
}

Upvotes: 0

Related Questions