Lance Samaria
Lance Samaria

Reputation: 19592

Swift -Property inside collectionView cell isn't updating after collectionView.performBatchUpdates > reloadItems(at:) runs

I have a collectionView cell that has an isExpanded: Bool property. When the cell first loads it is set to false and it only shows 1 line of text. If the text is several lines long I append "more ..." to the end of the first line and if the label is pressed I expand the cell. It works but I have to press the label twice to expand the cell and then twice again to collapse the cell back to 1 line.

What I've come to find out is when I first press the label I check to see if isExpanded == false and if it is I set it to true then pass the cell's index.item back in a protocol and call performBatchUpdates and then collectionView.reloadItems(at:).

After it runs I check isExpanded and instead of it being true it's false so the cell doesn't expand. If I press the label again now everything works the way it supposed to and the isExpanded is true and the cell expands.

Why do does the isExpanded property get set to false on the first go around even though I set it to true but on the second go around it stays set to true?

For a little more clarity

  1. isExpanded is initially false
  2. the label is tapped and isExpanded gets set to true
  3. after performBatchUpdates and reloadItems(at:) runs isExpanded somehow gets set back to false (this is the problem)
  4. after pressing the label once again isExpanded gets set to true
  5. after performBatchUpdates and reloadItems(at:) runs once again isExpanded is true (this is what should happen on the 3rd step).

It should be a 3 step process but it's always a 5 step process.

When collapsing the cell the same thing happens and I have to press the label twice for it to collapse.

Cell Class

protocol: MyCellDelegate: class {
    func expandOrCollapseCell(indexItem: Int)
}

weak var delegate: MyCellDelegate?
var indexItem: Int = 0
var isExpanded = false

var review: Review? {
    didSet {
        if let review = review else { return }

        // run logic to expand or collapse cell depending on wether isExpanded is true or false
    }
}

func tapGestureForLabel() {

    if !isExpanded {

       isExpanded = true

    } else {

       isExpanded = false

    }

    delegate?.expandOrCollapseCell(indexItem: self.indexItem)
}

And inside the class with the CollectionView

func expandOrCollapseCell(indexItem: Int) {

    let indexPath = IndexPath(item: indexItem, section: 0)

    UIView.animate(withDuration: 0) {

        self.collectionView.performBatchUpdates({ [weak self] in

           self?.collectionView.reloadItems(at: [indexPath])
           self?.collectionView.layoutIfNeeded()

    }) { (_) in
        print("finished updating cell")
       }
    }
}

I tried passing isExpanded in the protocol (I removed it) and inside the class with the CollectionView I updated the cell's isExpanded property like this but it made no difference

func expandOrCollapseCell(indexItem: Int, isExpanded: Bool) {

    if let cell = self.collectionView.cellForItem(at: indexPath) as? MyCell {

        cell.isExpanded = isCellExpanded
    }

    // perform batchUpdates ...
}

Upvotes: 1

Views: 348

Answers (1)

Shehata Gamal
Shehata Gamal

Reputation: 100503

This is a common problem of relying to the cell which is dequeued to hold a model state like

var isExpanded = false // should be inside model of each cell

you need to add this data to the model of the cell and check it when you need to change the state , then make the reload

Upvotes: 1

Related Questions