0

I am loading Gifs from GIPHY API, the thing is that Gifs are loading well BUT when I am scrolling way fast a bug occurs, it starts loading a GIF at instant T I start the scroll and reuses the cell. I want to make sure a gif can only be loaded for his dedicated cell. Actually, it loads the wrong one and the TIME of re-UPLOAD, the good gif overwrite the wrong, but it takes 1-2s depending connection, gif size. That's unacceptable for customer experience.

Here is my code:

    import Foundation
    import UIKit
    import FLAnimatedImage
    import KFSwiftImageLoader
    import PitPutSDK

    open class GifManager: NSObject, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
var controller: ConversationViewController
var collectionView: UICollectionView
var client = Config.clientGiphy
var trendsGif = [String?](repeating: "https://i0.wp.com/jenrose.com/wp-content/uploads/2016/11/mourning.jpg?w=256", count: 25)
var widthGif = [Int](repeating: 1000, count: 25)
var actualGifInput: String = ""

init(controller: ConversationViewController, collectionView: UICollectionView) {
    self.controller = controller
    self.collectionView = collectionView

    super.init()

    self.collectionView.register(UINib(nibName: "gifCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "gifCollectionViewCell")
}

public func sendTextForGifSearch(search: String? = "") {
    print("sendTextForGifSearch")
    guard let willFetchedSearch = search else {
        self.actualGifInput = ""
        return
    }
    self.actualGifInput = willFetchedSearch
    self.getTrendsGif(search: willFetchedSearch, limit: 25)
}

public func getTrendsGif(search: String? = "", limit: Int) {
    guard let fetchedSearch = search else {
        return
    }
    print("GET trends, for search \(String(describing: search))")
    if fetchedSearch != "" {
        let _ = client.search(fetchedSearch, limit: limit) { (response, error) in
            if let error = error as NSError? {
                print("Error \(error.localizedDescription) while loading Giphy Trends")
            }
            var i = 0
            if let response = response, let data = response.data {
                for result in data {
                    guard let gifURLs = result.images?.fixedHeightSmall?.gifUrl,
                        let gifWidths = result.images?.fixedHeightSmall?.width else {
                            print("No URL on response")
                            return
                    }
                    QueueManager.globalMainQueue.async {
                        self.trendsGif[i] = gifURLs
                        self.widthGif[i] = gifWidths
                        self.collectionView.reloadData()
                        i += 1
                    }
                }
            }
        }
    } else {
        let _ = client.trending(limit: limit) { (response, error) in

            if let error = error as NSError? {
                print("Error \(error.localizedDescription) while loading Giphy Trends")
            }

            var i = 0
            if let response = response, let data = response.data {
                for result in data {
                    guard let gifURLs = result.images?.fixedHeightSmall?.gifUrl,
                    let gifWidths = result.images?.fixedHeightSmall?.width else {
                        print("No URL on response")
                        return
                        }
                    QueueManager.globalMainQueue.async {
                        self.trendsGif[i] = gifURLs
                        self.widthGif[i] = gifWidths
                        self.collectionView.reloadData()
                        i += 1
                    }
                }
            } else {
                print("No Results Found")
            }
        }
    }
}

public func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
}

public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    print("Cell for Item AT \(indexPath)")
    print("Gifs : \(trendsGif)")

    let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "gifCollectionViewCell", for: indexPath) as! gifCollectionViewCell

    if let toPrintGif = trendsGif[indexPath.row] {
        if let gifURL: URL = (URL(string: toPrintGif)) {
            cell.gifView.animatedImage = nil

            QueueManager.chatPageDataSource.async {
                //cell.gifView.animatedImage = nil
                let gifData = try? Data(contentsOf: gifURL)
                cell.gifView.animatedImage = FLAnimatedImage(gifData: gifData)

            }
        }

    }
    return cell
}

public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: widthGif[indexPath.row], height: 100)
}

public func collectionView(_ collectionView: UICollectionView,
                           layout collectionViewLayout: UICollectionViewLayout,
                           insetForSectionAt section: Int) -> UIEdgeInsets {
    return UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)
}

public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return trendsGif.count
}

}

  • You should check if image you receive from web is belongs to model that you present in cell. – Andrew Jan 05 '18 at 12:15
  • It belongs to it, the question is how can i make sure each cell is kinda independent, the fact that cell are being reused fcks up the logic – Mouss Gherras Jan 05 '18 at 12:29
  • If you are using MVVM architecture you can bind ViewModel to your cell. Then in you ViewModel load this image and notify cell that you loaded this image and it should present it. So if viewModel is not bound to cell - then cell will not be modified. For example in `cellForItemAt` method do this `cell.bind(viewModel)` and inside cell subscribe to viewModel events. But don't forget to unsubscribe from them when you bind to cell another viewModel – Andrew Jan 06 '18 at 10:11
  • I'm using ReactiveCocoa to simplify binding between view models and views. – Andrew Jan 06 '18 at 10:15

0 Answers0