Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scrolling in UICollectionView selects wrongs cells - Swift

I have the following UICollectionView which is populated by an Array with NSManagedObject of type Categories

The problem is that when a Cell is selected scrolling does not function correctly. When scrolling through the UICollectionView other cells get selected, and deselected. Strange behaviour. I think this is because of the indexPath that is set incorrectly after scrolling? Anyway, I have been struggling with this for a couple of hours, and cannot seem to grasp it. Hopefully someone can point me in the right direction!

The fetchedCategory gets compared to the category to check if it is already selected and if they are the same the colors are inverted.

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    var cell = collectionView.dequeueReusableCellWithReuseIdentifier("CategorySelectionCollectionCell", forIndexPath: indexPath) as CategoryCollectionViewCell

    if fetchedCategories[indexPath.row] == category {
        cell.categoryLabel?.text = fetchedCategories[indexPath.row].name
        cell.categoryLabel?.textColor = UIColor.whiteColor()
        cell.backgroundColor = fetchedCategories[indexPath.row].iconColor as? UIColor
        collectionView.selectItemAtIndexPath(indexPath, animated: true, scrollPosition: UICollectionViewScrollPosition.None)
    } else {
        cell.categoryLabel?.text = fetchedCategories[indexPath.row].name
        cell.categoryLabel?.textColor = fetchedCategories[indexPath.row].iconColor as UIColor
        collectionView.deselectItemAtIndexPath(indexPath, animated: true)
    }

    return cell
}

func collectionView(collectionView: UICollectionView!, didSelectItemAtIndexPath indexPath: NSIndexPath!) {        
    var cell = collectionView.cellForItemAtIndexPath(indexPath) as CategoryCollectionViewCell

    cell.categoryLabel?.textColor = UIColor.whiteColor()
    cell.backgroundColor = fetchedCategories[indexPath.row].iconColor as? UIColor

    category = fetchedCategories[indexPath.row]
}

func collectionView(collectionView: UICollectionView!, didDeselectItemAtIndexPath indexPath: NSIndexPath!) {
    if var cell = collectionView.cellForItemAtIndexPath(indexPath) as? CategoryCollectionViewCell {
        cell.categoryLabel?.text = fetchedCategories[indexPath.row].name
        cell.categoryLabel?.textColor = fetchedCategories[indexPath.row].iconColor as UIColor
        cell.backgroundColor = UIColor.whiteColor()
    }
}
like image 386
Hugo Avatar asked Sep 29 '22 06:09

Hugo


1 Answers

You don't want to call cellForItemAtIndexPath and configure the cells in the didSelectItemAtIndexPath or didDeselectItemAtIndexPath delegate methods.
Also, you shouldn't be calling selectItemAtIndexPath and deselectItemAtIndexPath from within the cellForItemAtIndexPath method.

Instead, just keep track and toggle the state of the selected category in your select/deselect callbacks, and then don't do anything other the set up up the look of your cells in cellForItemAtIndexPath.

As the commenter pointed out, the cells are re-used, so stick to the simple way the delegate callbacks are designed to be used, and you should have much better luck.

If you need to refresh the look of the cells, do it by relying on cellForItemAtIndexPath being called while scrolling and using the reloadData and reloadItemsAtIndexPaths collection view methods if you need to force an update.

like image 146
Matt R Avatar answered Oct 03 '22 03:10

Matt R