Search code examples
swiftlabelnstimeruicollectionviewcellreloaddata

How to create a method that refreshes a UICollectionViewCell every second?


I have a UICollectionViewCell. In this cell, I have a label named cellTitle which I declared in the top level of the class:

var cellTitle = UILabel()

I change the text of this label in each cell in the cellForItemAtIndexPath method:

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
cellTitle = UILabel(frame: CGRectMake(0, 0, cell.bounds.size.width, 160))
cellTitle.numberOfLines = 3
cell.contentView.addSubview(cellTitle)
switch indexPath.item {
    case 0:
        cellTitle.text = definitions[0]
    case 1:
        cellTitle.text = definitions[1]
    case 2:
        cellTitle.text = definitions[2]
    case 3:
        cellTitle.text = definitions[3]
    case 4:
        cellTitle.text = definitions[4]
    case 5:
        cellTitle.text = definitions[5]
    case 6:
        cellTitle.text = definitions[6]
    case 7:
        cellTitle.text = boatTypes[0]
    case 8:
        cellTitle.text = boatTypes[1]
    case 9:
        cellTitle.text = boatTypes[2]
    case 10:
        cellTitle.text = boatTypes[3]
    case 11:
        cellTitle.text = boatTypes[4]
    case 12:
        cellTitle.text = boatTypes[5]
    case 13:
        cellTitle.text = boatTypes[6]
    case 14:
        cellTitle.text = "Press to quit game. Time left: \(timerText) seconds"
    default:
        break
    }
    return cell
}

As you can see, on cell 14, I have the text not set to an element from an array. I am using timerText from a timer I created that counts down at an interval of 1 second. The problem is that the text in cell 14 that is timerText is not updating, it just stays at what I first set it to, which is 45. How can I create a refresh method only for cell 14 that doesn't cause errors? Thank you for the support!


Solution

  • Have your timer routine call reloadItemsAtIndexPaths for that cell:

    myCollectionView.reloadItemsAtIndexPaths([NSIndexPath(forItem: 14, inSection: 0)])
    

    I have updated your collectionView:cellForItemAtIndexPath: to add a tag to the UILabel so that it can be reused. I also collapsed your common cases in the switch. I haven't compiled this, but it should be close.

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let specialTag = 123
        var cellTitle: UILabel
    
        if let oldCell = cell.contentView.viewWithTag(specialTag) as? UILabel {
            // Just reuse the label if it is already there
            cellTitle = oldCell
        } else {
            // Don't have one?  Add a new label and give it a tag so we can find it
            // the next time.
            cellTitle = UILabel(frame: CGRectMake(0, 0, cell.bounds.size.width, 160))
            cellTitle.numberOfLines = 3
            cellTitle.tag = specialTag
            cell.contentView.addSubview(cellTitle)
        }
        switch indexPath.item {
        case 0...6:
            cellTitle.text = definitions[indexPath.item]
        case 7...13:
            cellTitle.text = boatTypes[indexPath.item - 7]
        case 14:
            cellTitle.text = "Press to quit game. Time left: \(timerText) seconds"
        default:
            break
        }
        return cell
    }