Ashish Sharma
Ashish Sharma

Reputation: 663

Found nil while setting value of a label inside Collection view cell

Case:

I'm using a collection view inside a UIView, I've connected it as an outlet called 'partsCollectionView'. I've created a cell with identifier 'cell' and a custom class 'SelectionCollectionViewCell' for that cell. Inside the cell, I've got a label called 'cellTitle'.

Error: Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

I'm facing the error while setting the value of that label inside 'cellForItemAt' Method.

Here are the concerned views:

Cell description,

Cell Description Image

and, collection View Description

The collection View

The Cell Class is:

import UIKit

class SelectionCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var cellTitle: UILabel!
}

The class where I'll use the collection view is:

import UIKit

private let reuseIdentifier = "cell"

let array = ["small","Big","Medium","Very big","Toooo big String","small"]

class SelectionCollectionViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

    @IBOutlet weak var partsCollectionView: UICollectionView!

    @IBOutlet weak var instructionsView: UITextView!
    @IBOutlet weak var image: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.partsCollectionView.register(SelectionCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)

    }


     func numberOfSections(in collectionView: UICollectionView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }


     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return array.count
    }

     func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = partsCollectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! SelectionCollectionViewCell

        cell.layer.cornerRadius = 10
        cell.clipsToBounds = true

        cell.cellTitle.text = array[indexPath.row]

        cell.layer.borderColor = #colorLiteral(red: 0.07843137255, green: 0.6862745098, blue: 0.9529411765, alpha: 0.6819349315)
        cell.layer.borderWidth = 2

        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        let name = array[indexPath.row]

        let attributedName = NSAttributedString(string: name)

        let width = attributedName.widthWithConstrainedHeight(height: 20.0)

        return CGSize(width: width + 40, height: 30.0)
    }
}

extension NSAttributedString {

    func widthWithConstrainedHeight(height: CGFloat) -> CGFloat {
        let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, context: nil)

        return boundingBox.width
    }
}

Update: This is how it looks if I skip setting the title text. The title will come inside those rounded boxes.

How it looks without Setting title

Upvotes: 0

Views: 1876

Answers (2)

RajeshKumar R
RajeshKumar R

Reputation: 15778

Remove this line from viewDidLoad.

    self.partsCollectionView.register(SelectionCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)

When you register a cell programmatically it creates a new collection view cell object. It doesn't get the cell from storyboard. So cellTitle will be nil

OR

Programmatically initialize the label in custom collection view cell

class SelectionCollectionViewCell:UICollectionViewCell {
    let  cellTitle = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)
        addSubview(cellTitle)
        cellTitle.frame = CGRect(x: 10, y: 10, width: 100, height: 30)
    }
}

Upvotes: 4

PPL
PPL

Reputation: 6565

Just minor mistake is there I think, In cellForItemAt indexPath Please update following line,

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! SelectionCollectionViewCell

I just paste your code and got following output, nothing else,

enter image description here

If you still unable to produce desired output, just delete existing UILabel from SelectionCollectionViewCell and add it again.

FYI. No need to register cell in viewDidLoad() method

Upvotes: 2

Related Questions