0
votes

Sorry for the vague title but I wasn't completely sure was to call it. I have a list of collection view cells in a collectionview these cells just have a white background. I have a total of 20 cells and I want the first one to have a cyan background and the fourth to have a green background. My issue is that if the list is big enough and I scroll the colors seem to be random sometimes 4 green and 2 cyan at the top instead of just 1 cyan and 1 green. I think this is due to using index path.row in the func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell method and assigning colors based on indexpath.row. I think index path.row changes as I scroll so when I scroll to the bottom index path.row is the item at the top of the screen not the top of the list. I understand this is not the proper way to achieve this, is there anyway to get the first/last item from the list instead of the first/last currently on my screen? Is there a better way to go about this entirely?

Here is a quick example of what the issue looks like - https://gyazo.com/e66d450e9ac50b1c9acd521c959dd067

EDIT:

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int` is return 20 and in `func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell` this is what I have - `let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Invite Cell", for: indexPath) as! InviteCell
    print(indexPath.row)

    if indexPath.row == 0 {
        cell.InviteCellContainer.backgroundColor = UIColor.cyan
    } else if indexPath.row == 5 {
        cell.InviteCellContainer.backgroundColor = UIColor.green
    }
    return cell
}
3

3 Answers

2
votes

Cells are reused. Make sure that any UI element has a defined state in cellForItemAt:

In your code the state is undefined if the row is not 0 and not 5. So you need to add a case for all other indexes:

if indexPath.row == 0 {
    cell.InviteCellContainer.backgroundColor = UIColor.cyan
} else if indexPath.row == 5 {
    cell.InviteCellContainer.backgroundColor = UIColor.green
} else {
    cell.InviteCellContainer.backgroundColor = UIColor.gray // or what the default color is
}
return cell

A more descriptive syntax is a switch expression

switch indexPath.row {
    case 0: cell.InviteCellContainer.backgroundColor = UIColor.cyan
    case 4: cell.InviteCellContainer.backgroundColor = UIColor.green
    default: cell.InviteCellContainer.backgroundColor = UIColor.gray
}
0
votes

Assuming your code isn't faulty, which I can't tell because you didn't include any of it, it looks like you should be calling collectionView.reloadData() after each cellForItemAt. Let me know what happens when you do this.

0
votes

You should set the background color regardless of its place

if(indexPath.row == 0) {
    cell.InviteCellContainer.backgroundColor = UIColor.cyan
} else if(indexPath.row == 5) {
    cell.InviteCellContainer.backgroundColor = UIColor.green
} else {
    cell.InviteCellContainer.backgroundColor = UIColor.white
}
return cell

It might be because you haven't defined the cell in a separate class and used the function prepareForReuse() to set the background back to white. Cells are reused within a collectionView so sometimes if you set the data (and don't reset it) it will remain the same when the cell is used again. Hope this helps!