iosswiftswift3uicollectionviewcelluicollectionviewdelegate

Setting label text in a UICollectionViewCell not working when string is passed to custom class


I am setting up a UICollectionView with a custom UICollectionViewCell Class.

Using the functions specified in the UICollectionViewDelegate I have been able to get a label populated with text in each cell.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "keypadButton", for: indexPath) as! KeypadButtonCollectionViewCell
    cell.awakeFromNib()
    return cell
}


func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    let button = cell as! KeypadButtonCollectionViewCell

    //Assigning like this works
    button.buttonLabel.text = tempScale[indexPath.row] 
}

However;

I initially had it set up differently with a buttonText class variable in the KeypadButtonCollectionViewCell Class (as below) and setting that variable in the willDisplay function (also below)

class KeypadButtonCollectionViewCell: UICollectionViewCell {


    var buttonLabel: UILabel!
    var buttonText: String!

    override func awakeFromNib() {
        buttonLabel = UILabel.init(frame: contentView.frame)
        buttonLabel.font = UIFont.init(name: "HelveticaNeue-Ultralight", size: 20)
        buttonLabel.textColor = UIColor.black
        buttonLabel.textAlignment = NSTextAlignment.center

        buttonLabel.text = buttonText //Assigning here didn't work

        contentView.layer.borderColor = UIColor.init(red: 37/255, green: 37/255, blue: 37/255, alpha: 1).cgColor
        contentView.layer.borderWidth = 4
        contentView.addSubview(buttonLabel)

    }

}


//---------In the view controller--------

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    let button = cell as! KeypadButtonCollectionViewCell

    //Setting class var string here to be set as label.text not working
    button.labelText = tempScale[indexPath.row] 
}

What is it I am misunderstanding here? Why did it not like setting the using the assigned class variable to set the label text in the wakeFromNib() method but worked when I set the label text directly?

As mentioned at the beginning, I have a working way of doing this, I am interested in this for academia and to better understand OOP programming.


Solution

  • awakeFromNib gets called automatically after the view and its subviews were allocated and initialized, so don't called it explicitly. So remove the line cell.awakeFromNib().

    In your case when awakeFromNib is called your buttonText String is nil and when willDisplay cell method call where you are setting String value buttonText but awakeFromNib is already called before that so setting buttonText there will not update the value of your label.

    From the documentation on awakeFromNib:

    The nib-loading infrastructure sends an awakeFromNib message to each object recreated from a nib archive, but only after all the objects in the archive have been loaded and initialized. When an object receives an awakeFromNib message, it is guaranteed to have all its outlet and action connections already established.

    The way you are doing with your first approach is perfect by setting array element directly to the label's text but if you want to set the String value buttonText then you can go for the observing property didSet of your buttonText like this way.

    var buttonText: String = "" {
        didSet {
            buttonLabel.text = buttonText
        }
    }
    

    Now when you set buttonText value in willDisplay cell it will update the value of cell's label because of didSet of your buttonText.