3

I have a CollectionView, I use the cells to display videos and I also store some other data on variables. And whenever I scroll I reuse previous cells using the following code:

let cell = collectionView.dequeueReusableCellWithReuseIdentifier("profileCell", forIndexPath: indexPath) as! ProfileCollectionViewCell

But I noticed that when I am using an indexPath I have previously used, I do not get back the same cell as previously but another cell apparently at a random order. I would like to avoid reloading the videos when it is not necessary.

Is there a way for me to get the same cell used with the same indexPath?

Thanks, Carlos

Alexey Pichukov
  • 3,377
  • 2
  • 19
  • 22
carlosb
  • 182
  • 2
  • 8
  • 1
    Possible duplicate of [UICollectionView - Image is getting set randomly](http://stackoverflow.com/questions/23013935/uicollectionview-image-is-getting-set-randomly) – casillas Nov 04 '15 at 19:36

3 Answers3

0

You are using reusable cells. With that you can't be sure you got always the same cell, it's almost always the other way around. You could try with storing the cells when first loaded, then checking it in cellForRow.. but in my opinion better way would be to store videos to file (of course with a limit), because storing cells isn't the best option.

sunshinejr
  • 4,834
  • 2
  • 22
  • 32
0

You cannot influence which cell instance you get back from dequeueReusableCellWithReuseIdentifier. So you cannot keep the video in the cell when the cell is scrolled offscreen.

What you can do is add a NSMutableDictionary property to your view controller and store references to your videos in it (use the cell's indexPath as key). You can store the references in tableView(_:didEndDisplayingCell:forRowAtIndexPath:).

Then when you get a cell from dequeueReusableCellWithReuseIdentifier you retrieve to video from the dictionary and add it to the cell. That way it does not matter which cell you get back from the queue.

joern
  • 27,354
  • 7
  • 90
  • 105
0

That's how collectionView.dequeueReusableCellWithReuseIdentifier works. If you want to go around this functionality you could save all cells that are created in an array and then instead of dequeueing you could fetch the one with the video already loaded. However, if you use some framework that caches the videos after loading them you shouldn't need to deal with this at all.

var cells: [CustomCollectionViewCell] = []

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        var cell:CustomCollectionViewCell?
        if cells.count >= indexPath.row {
            cell = cells[indexPath.row]
        } else {
            cell = CustomCollectionViewCell()
            //setup cell
            cells.append(cell)
        }

        return cell!
    }

Disclaimer:

This solution is a hack. As mentioned by @Async in the comment below this solution will use a lot of memory if you create a lot of cells.

Moriya
  • 7,750
  • 3
  • 35
  • 53
  • seriously, this is very annoying, and while deque is supposed to unload memory usage, we have to load it even more with holding arrays, and it presents additional problems when your table is updated all the time, with possible reduce of the number of cells (so this example will not work) – Async- Oct 11 '16 at 09:39
  • This depends very much on how many rows you are planning to load in the table view. The code will work but as you mention it will use a lot more memory. It will probably also slow down the fist scroll. But it all depends on how and where you use it. In a screen with 10-20 videos in a list I seriously doubt you'll have an issue. if we are talking 100s of rows then maybe... – Moriya Oct 11 '16 at 09:48
  • in my case is slightly different: i need to load many cells (around 70-100) and highlight certain ones depending on condition, but this highlight is wrong when dequeue is used ALWAYS.. I'm really angry)) – Async- Oct 11 '16 at 09:56
  • So save the highlight status in an array `shouldbeHighlighted: [Bool]` and make sure to set the highlight from that array every time you dequeue a cell. The important part is to also remove the highlight if it should not be there after the cell is dequeued. – Moriya Oct 11 '16 at 10:03
  • BTW if `cells.count` equals `indexPath.row` this solution will crash the App. `if cells.count > indexPath.row {` or for better reading `if indexPath.row < cells.count {` should be used instead. – Gian Franco Zabarino Apr 29 '17 at 01:34