iosswiftuicollectionviewuicollectionviewcelluicollectionviewdelegate

UICollectionView.reloadData() changes cell order | iOS Swift


So I am working with a simple UICollectionView, 3 columns by X rows, where X is set by the variable matchesFromSelectedSession.count + 1. Here are the delegate functions that I am using for my collectionView:

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

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    let cellHeight = 15.0 as CGFloat
    return CGSizeMake(collectionView.bounds.size.width/3, cellHeight)
}

func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return matchesFromSelectedSession.count + 1
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let reuseIdentifier = "MatchCollectionViewCell"
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! MatchCollectionViewCell
    cell.matchCollectionLabel = UILabel(frame: CGRectMake(0,0,collectionView.bounds.width/3 - 3.0,15))
    cell.matchCollectionLabel.textColor = UIColor.blackColor()
    cell.systemLayoutSizeFittingSize(cell.frame.size, withHorizontalFittingPriority: UILayoutPriorityDefaultHigh, verticalFittingPriority: UILayoutPriorityDefaultLow)
    cell.matchCollectionLabel.font = UIFont(name: "Helvetica Neue", size:12)
    if indexPath.section == 0 {
        switch indexPath.row {
        case 0:
            cell.matchCollectionLabel.text = "Match #"
            cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
            cell.matchCollectionLabel.textAlignment = NSTextAlignment.Right
            break
        case 1:
            cell.matchCollectionLabel.text = "Record"
            cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
            cell.matchCollectionLabel.textAlignment = NSTextAlignment.Center
            break
        case 2:
            cell.matchCollectionLabel.text = "Outcome"
            cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
            break
        default:
            cell.matchCollectionLabel.text = ""
            cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
            break
        }
    } else {
        switch indexPath.row {
        case 0:
            cell.matchCollectionLabel.text = "\(indexPath.section)"
            if indexPath.section%2 == 0 {
                cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
            }
            cell.matchCollectionLabel.textAlignment = NSTextAlignment.Right
            break
        case 1:
            cell.matchCollectionLabel.text = matchesFromSelectedSession[indexPath.section - 1].matchRecord()
            if indexPath.section%2 == 0 {
                cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
            }
            cell.matchCollectionLabel.textAlignment = NSTextAlignment.Center
            break
        case 2:
            let outcome = matchesFromSelectedSession[indexPath.section - 1].matchOutcome()
            switch outcome {
            case "W":
                cell.matchCollectionLabel.text = "Win"
                cell.matchCollectionLabel.textColor = UIColor.greenColor()
                break
            case "D":
                cell.matchCollectionLabel.text = "Draw"
                cell.matchCollectionLabel.textColor = UIColor.blueColor()
                break
            case "L":
                cell.matchCollectionLabel.text = "Loss"
                cell.matchCollectionLabel.textColor = UIColor.redColor()
                break
            default:
                cell.matchCollectionLabel.textColor = UIColor.blackColor()
                break
            }
            if indexPath.section%2 == 0 {
                cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
            }
            break
        default:
            if indexPath.section%2 == 0 {
                cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
            }
            cell.matchCollectionLabel.text = ""
            break
        }
    }
    //add subview if new cell otherwise tag cell to know to reuse next time
    if cell.tag != 19 {
        cell.addSubview(cell.matchCollectionLabel)
    }
    cell.tag = 19
    return cell
}

The custom cell I use, MatchCollectionViewCell, only contains one label, matchCollectionLabel and that is it. I use self.matchCollectionView.reloadData() in the viewDidAppear function of the view for when a secondary view changes the table and dismisses back to this original view.

I tag the cells after the first use that I am not constantly adding unnecessary subviews to the cell after every viewDidAppear.

The table looks great after the initial setup but after reloadData is called, the collectionView's cell order gets changed and jumbled. If I edit the number of cells, reloadData() updates to correctly show the cell number change but the cells are still in an incorrect order.

Here is a picture of before and after reloadData

https://i.sstatic.net/8sDKC.png

Any help would be greatly appreciated! Thanks!


Solution

  • You are creating a new label every time. You only add it as a subview if the tag isn't 19 but you always allocate a new label.

    This means that when you reuse a cell, you are updating a new label, not the one that has been added to the cell, so your changes aren't visible.

    You can either move your tag check to the top of the function and use that to control the allocation of the label, or define matchCollectionLabel as an optional and then you can check it for nil:

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let reuseIdentifier = "MatchCollectionViewCell"
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! MatchCollectionViewCell
    
        if cell.matchCollectionLabel == nil {
            cell.matchCollectionLabel = UILabel(frame: CGRectMake(0,0,collectionView.bounds.width/3 - 3.0,15))
            cell.matchCollectionLabel!.textColor = UIColor.blackColor()
            cell.systemLayoutSizeFittingSize(cell.frame.size, withHorizontalFittingPriority: UILayoutPriorityDefaultHigh, verticalFittingPriority: UILayoutPriorityDefaultLow)
            cell.matchCollectionLabel!.font = UIFont(name: "Helvetica Neue", size:12)
            cell.addSubview(cell.matchCollectionLabel!)
        }
    
        if indexPath.section == 0 {
            switch indexPath.row {
            case 0:
                cell.matchCollectionLabel!.text = "Match #"
                cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
                cell.matchCollectionLabel!.textAlignment = NSTextAlignment.Right
                break
            case 1:
                cell.matchCollectionLabel!.text = "Record"
                cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
                cell.matchCollectionLabel!.textAlignment = NSTextAlignment.Center
                break
            case 2:
                cell.matchCollectionLabel!.text = "Outcome"
                cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
                break
            default:
                cell.matchCollectionLabel!.text = ""
                cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
                break
            }
        } else {
            switch indexPath.row {
            case 0:
                cell.matchCollectionLabel!.text = "\(indexPath.section)"
                if indexPath.section%2 == 0 {
                    cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
                }
                cell.matchCollectionLabel!.textAlignment = NSTextAlignment.Right
                break
            case 1:
                cell.matchCollectionLabel!.text = matchesFromSelectedSession[indexPath.section - 1].matchRecord()
                if indexPath.section%2 == 0 {
                    cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
                }
                cell.matchCollectionLabel!.textAlignment = NSTextAlignment.Center
                break
            case 2:
                let outcome = matchesFromSelectedSession[indexPath.section - 1].matchOutcome()
                switch outcome {
                case "W":
                    cell.matchCollectionLabel!.text = "Win"
                    cell.matchCollectionLabel!.textColor = UIColor.greenColor()
                    break
                case "D":
                    cell.matchCollectionLabel!.text = "Draw"
                    cell.matchCollectionLabel!.textColor = UIColor.blueColor()
                    break
                case "L":
                    cell.matchCollectionLabel!.text = "Loss"
                    cell.matchCollectionLabel!.textColor = UIColor.redColor()
                    break
                default:
                    cell.matchCollectionLabel!.textColor = UIColor.blackColor()
                    break
                }
                if indexPath.section%2 == 0 {
                    cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
                }
                break
            default:
                if indexPath.section%2 == 0 {
                    cell.backgroundColor = ImageEditor.colorWithHexString("EFEFF4")
                }
                cell.matchCollectionLabel!.text = ""
                break
            }
        }
        return cell
    }