-1

I'm trying to show some images and hide others using ".isHidden" in my CollectionView. But when I scroll down or reload the collectionView they either get reordered incorrectly or hidden entirely.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ReadBookCell", for: indexPath) as! ReadBookCell
    
    let item = readBookArray[indexPath.item]

        for star in cell.starImgOutletCollection {
            if star.tag <= item.starRating {
                star.isHidden = false

            } else {     
                    star.isHidden = true
            }

        }   

    return cell
}

Edit: Here is my prepareForReuse

 override func prepareForReuse() {
    super.prepareForReuse()
    for star in starImgOutletCollection {
        star.isHidden = true
    }  
}
Jordan
  • 127
  • 1
  • 1
  • 9
  • Perhaps you also need to share the implementation of prepareForReuse of your cell class. – valeCocoa Mar 09 '22 at 18:41
  • @valeCocoa I didn't use prepareForReuse at all. Could that be the problem? – Jordan Mar 09 '22 at 18:45
  • Well when a cell gets dequeued and was previously in use it should reset its view, and that is usually done in prepareForReuse method. In your case you might want to set all the stars to hidden. Then in cellForRow data source method you might as well just un hide those that should be visible based on the represented model. – valeCocoa Mar 09 '22 at 18:53
  • @valeCocoa I just tried doing that and it's still doing the same thing. – Jordan Mar 09 '22 at 19:06
  • 1
    Then problem might also lie in the tag value of those subviews. Without the code of the cell subclass I can’t really help you at this point. – valeCocoa Mar 09 '22 at 19:15
  • @Jordan - the code you posted shows you manipulating `starImgOutletCollection` and `starButtonCollection` ... do you have a set of **buttons** and a set of **imageViews**? Also, are your "stars" (whatever they are) in a horizontal `UIStackView`? – DonMag Mar 12 '22 at 14:07
  • @DonMag It is a set of ImageViews. I accidentally misnamed them when I posted the question. The system image stars are in a horizontal UIStackView as well. – Jordan Mar 12 '22 at 20:16
  • Don't use tags. There is no need. If you have a properly formed outlet collection, you can use index numbers within that collection. – matt Mar 13 '22 at 14:00
  • @Jordan - to clarify your question... on **initial display** are your "rating stars" displayed correctly? If so, is the problem that you have code to ***change the rating*** -- but then scrolling/reloading does not reflect the new rating? – DonMag Mar 13 '22 at 14:07
  • The problem is that you have not provided sufficient code for us to run the actual project and see the issue before our own eyes. – matt Mar 13 '22 at 15:35

1 Answers1

0

Assuming your "stars" are 5 image views in a stack view like this:

enter image description here

And, assuming your starRating will be between 0 and 5 (Zero being no rating yet)...

In your cell class, create a reference to the stack view - since your question mentions starImgOutletCollection I'm assuming you are using @IBOutlet (that is, not creating your views via code), so:

@IBOutlet var starsStackView: UIStackView!

Then, still in your cell class, add this func:

func updateStars(_ starRating: Int) {
    for i in 0..<starsStackView.arrangedSubviews.count {
        starsStackView.arrangedSubviews[i].isHidden = i >= starRating
    }
}

Now, in cellForRowAt

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ReadBookCell", for: indexPath) as! ReadBookCell
    
    let item = readBookArray[indexPath.item]

    cell.updateStars(item.starRating)

    // do the other stuff to set labels, images, etc
    //  in the cell    

    return cell
}

You no longer need the outlet collection for the "star" image views, and you no longer need to implement prepareForReuse().

DonMag
  • 69,424
  • 5
  • 50
  • 86
  • Elegant. But you haven't explained what was wrong with the OP original code. – matt Mar 13 '22 at 13:58
  • @matt - no, I guess I haven't... I guess the OP's mismatched `starImgOutletCollection` and `starButtonCollection` caused me to think that was the issue. – DonMag Mar 13 '22 at 14:05
  • I don't see any `starButtonCollection`. – matt Mar 13 '22 at 14:11
  • @matt - prior to the OP's edit (see comments on OP). – DonMag Mar 13 '22 at 14:15
  • @DonMag Now all the star ratings are properly loaded when the collectionView is first viewed. When I scroll then the cell items that have only one star gets hidden. But all the other stars seem to be working as they should. Seems really weird to me – Jordan Mar 13 '22 at 20:13
  • @Jordan - well, that doesn't make any sense. I think you need to do some debugging of your data. When you scroll, are you getting the expected `.starRating` in `cellForRowAt`? Is something changing that `.starRating`? You may need to put together a [mre] so we can see exactly what you're doing. – DonMag Mar 15 '22 at 12:46