4

I am trying to use a UICollectionView to display a square MyCollectionViewCell that has animated GIFs in a UIImageView.

Rows and sections are setup like so:

override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1
}

override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 50
}

I'm using SwiftGif to get GIFs assigned to the cell's UIImageView like so:

let gifs = [UIImage.gifWithName("gif1"), UIImage.gifWithName("gif2"), UIImage.gifWithName("gif3")]

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("gifCell", forIndexPath: indexPath) as! GifCollectionViewCell
    cell.gifImageView.image = gifs[indexPath.item % gifs.count]
    return cell
}

Everything for the most part works great. But my issue is that when scrolling, there are times when cell is blank and no GIF appears. In the debugging process, I've added a label to the cell to display the indexPath.item, as you can see in code above, to make sure that the cell isn't getting passed over and have found that the label will always display indexPath even if the cell does not display a GIF.

I have tested with regular images instead like so:

let testImages = [UIImage(named: "testImage1"), UIImage(named: "testImage2", UIImage(named: "testImage3")]

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("gifCell", forIndexPath: indexPath) as! GifCollectionViewCell
    cell.gifImageView.image = testImages[indexPath.item % testImages.count]
    return cell
}

and had no occurrences of blank cells.

Even more curious, when I originally actually built the GIF in collectionView(...cellForItemAtIndexPath) I did not get any issues with blank cells either:

let gifNames = ["gif1", "gif2", "gif3"]

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("gifCell", forIndexPath: indexPath) as! GifCollectionViewCell
    let gif = UIImage.gifWithName(gifNames[indexPath.item % gifNames.count])
    cell.gifImageView.image = gif
    return cell
}

This original implementation would have worked if it weren't for the fact the GIF build process drastically affects the scrolling performance of the UICollectionView which is what forced me to change implementation in the first place.

I have confirmed that this is not an issue with SwiftGif as I have replicated this issue in a different application using an animation render library and an AnimatedView in place of the UIImageView in MyCollectionViewCell and displayed animations instead of GIFs and got the same issue with cells randomly showing nothing instead of the animation when scrolling through the CollectionView.

I have tried the StackOverflow solution here and implemented a custom UICollectionViewFlowLayout like so:

class MyFlowLayout: UICollectionViewFlowLayout {
    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let attributes = super.layoutAttributesForElementsInRect(rect)
        let contentSize = self.collectionViewContentSize()
        let newAttrs = attributes?.filter { $0.frame.maxX <= contentSize.width && $0.frame.maxY <= contentSize.height}
        return newAttrs
    }
}

And assigned it in viewDidLoad() like so:

self.collectionView?.collectionViewLayout = MyFlowLayout()

In MyFlowLayout I have also tried:

override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
    return true
}

I have also messed with various cell sizes (width 1 less than height, height 1 less than width etc) and messed around with some section inset combinations but have not managed to find the source of this issue that is causing the animated view to not to show up.

Any help would be appreciated. Thanks

Community
  • 1
  • 1
DerFlickschter
  • 1,031
  • 1
  • 8
  • 18

1 Answers1

0

I solved the issue by setting the gifImageView.image = nil in collectionView(...cellForItemAtIndexPath) before assigning the image.

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCellWithReuseIdentifier("gifCell", forIndexPath: indexPath) as! GifCollectionViewCell
    cell.gifImageView.image = nil    // Added this line
    cell.gifImageView.image = gifs[indexPath.item % gifs.count]
    cell.infoLabel.text = String(indexPath.item)
    return cell
} 

Not sure how/why this fixed it but it works now.

DerFlickschter
  • 1,031
  • 1
  • 8
  • 18