Swift custom UITableViewCell label is always nil
Asked Answered
T

11

29

I've been stuck with this problem for days, so I'd be really happy if someone could help. I'm trying to create a dynamic UITableView, for which I created a custom UITableView subclass and I've created a custom UITableViewCell subclass as well, because I need several UILabels and a UIButton in each cell. The cell is created, but the problem is that the value of the labels is always nil, hence the cell isn't displayed properly. This is, how the storyboard looks like, and this is what I see while running the program.

Here's my UITableViewCell subclass:

import UIKit

class QuestionTableViewCell: UITableViewCell {

    @IBOutlet var student: UILabel!
    @IBOutlet var labDesk: UILabel!
    @IBOutlet var topic: UILabel!
    @IBOutlet var answers: UILabel!

}

and my UITableView subclass:

import UIKit

class QuestionViewController: UITableViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet var table: UITableView!
     struct Question {
        var student: String
        var labDesk: String
        var topic: String
        var answered: String
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        table.estimatedRowHeight = 50
        table.dataSource = self
        table.delegate = self
        self.table.registerClass(QuestionTableViewCell.self, forCellReuseIdentifier: "cell")
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("cell") as QuestionTableViewCell
        cell.student.text = "random string"
        cell.labDesk?.text = "25/A"
        cell.topic?.text = "string"
        cell.answers?.text = "3"
        return cell
    }
}
Transfix answered 13/3, 2015 at 15:16 Comment(2)
try dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) and make sure your cell id matches, and if the cell is not optional, you shouldn't have to use cell.labDesk?.text, just cell.labDesk.textAccouchement
I already tried that and it gives my this exception: 2015-03-13 15:31:09.626 LABhelper[40046:5574601] *** Assertion failure in -[UITableView dequeueReusableCellWithIdentifier:forIndexPath:], /SourceCache/UIKit_Sim/UIKit-3318.16.14/UITableView.m:6116 This is how my function looks like after what you suggested if I got it right: var cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as QuestionTableViewCell I didn't make them optional, but somehow they became optionals, so without the ? the build fails.Transfix
E
74

Try removing self.table.registerClass(QuestionTableViewCell.self, forCellReuseIdentifier: "cell")

Enlargement answered 28/5, 2015 at 22:24 Comment(5)
Its working fine. But why we are removing this line bcz its registering the customcell rite?Chemotherapy
@Chemotherapy because the class is already present in the interface builder.Boxfish
I removed this line and mine worked. Kind of confusing why I didn't need it, my guess is setting the custom class in the Interface builder does the same function as registering the custom cell class?Keystone
This is correct and helped me find the solution to my issue at the following URL... my nib/custom cell was being registered incorrectly gist.github.com/gonzalezreal/92507b53d2b1e267d49aDoolittle
Wow, super helpful! This was also my issue. In my case it worked fine until I would scroll my CollectionView, a simple list of labels. As soon as I scrolled a new row into view it crashed with a nil value. Thank you!Innervate
H
29

If you're using a cell with a nib then make sure that you are registering the cell with the table view using registerNib:forCellReuseIdentifier:. If the cell just has a class then use registerClass:forCellReuseIdentifier:.

Homogeneity answered 3/10, 2015 at 11:12 Comment(1)
If you are using a nib, the exact syntax that you will need is: tableView.registerNib(UINib(nibName: "YOURNIBNAME", bundle: nil), forCellReuseIdentifier: "YOURREUSEID")Jena
A
8

First, you don't have to register the class if it exists in Interface Builder.

Second, you should dequeueReusableCellWithIdentifier:forIndexPath instead of dequeueReusableCellWithIdentifier.

Third, UITableViewController already has a property called tableView so there is no need to make an IBOutlet to table as UITableViewController already handles this. It also conforms to the UITableViewDataSource and UITableViewDataSource so these are extraneous.

Fourth, don't set the properties for table set them for tableView.

Fifth, cell.labDesk.text = "" is sufficient, no need to make it optional.

If all your IBOutlets are hooked up, Cell Identifiers correctly set, and these revisions are made, it will work.

class QuestionTableViewCell: UITableViewCell {

    @IBOutlet var student: UILabel!
    @IBOutlet var labDesk: UILabel!
    @IBOutlet var topic: UILabel!
    @IBOutlet var answers: UILabel!

}


class QuestionViewController: UITableViewController {

    struct Question {
        var student: String
        var labDesk: String
        var topic: String
        var answered: String
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.estimatedRowHeight = 50
        tableView.dataSource = self
        tableView.delegate = self
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as QuestionTableViewCell
        cell.student.text = "random string"
        cell.labDesk.text = "25/A"
        cell.topic.text = "string"
        cell.answers.text = "3"
        return cell
    }
}
Accouchement answered 13/3, 2015 at 15:50 Comment(7)
What I already told you happens, if it isn't optional, it doesn't run. cell.student.text = "random string" fatal error: unexpectedly found nil while unwrapping an Optional valueTransfix
Does it not compile or does it crash as soon as it opens?Accouchement
It crashes as soon as I reach the UITableViewTransfix
Because this code works, so it could be your IBOutlets not properly connectedAccouchement
ah, you're using a view controller with a table view inside of it, note this is not a UITableViewControllerAccouchement
The fix: Delete your view controller, replace it with a UITableViewController in interface builder, set its class to be QuestionViewController, reimplement the cell and reconnect the outlets and you should be goodAccouchement
It is a UITableViewController, I already deleted it and readded and then changed it's class to QuestionViewControllerTransfix
E
8

The most important part is to register the xib containing the custom cell with the table view. Therefore add the following code in viewDidLoad() method.

let nib = UINib.init(nibName: "MyCustomCell", bundle: nil)    
self.tblUsers.register(nib, forCellReuseIdentifier: "MyCustomCell")
Eiffel answered 7/1, 2020 at 11:58 Comment(0)
N
3

I might be late here, but I just solved a similar problem.

Make sure you've set the Identifier in InterfaceBuilder on your UITableViewCell.

enter image description here

Nyctalopia answered 20/4, 2015 at 5:40 Comment(0)
D
2

For those who are still trying to figure this out after trying all those possible solutions:

Disconnect/Reconnect the IBOutlets in your Storyboards should do the trick!

Delfeena answered 19/1, 2018 at 11:41 Comment(0)
M
1

Don't forget to add:

tableView?.register(UINib(nibName: "xyz",
                           bundle: nil),
                    forCellReuseIdentifier: "abc")
Masonite answered 29/9, 2020 at 18:50 Comment(0)
C
0

If you are using a table cell with Xib. you need to register your cell with ..

register(_:forCellReuseIdentifier:)
Clubman answered 27/11, 2019 at 14:32 Comment(0)
B
0

If you haven't added constraints for the label then they will not be created though the custom cell is created. Make sure you added some constraints.

Bandylegged answered 1/5, 2020 at 20:1 Comment(1)
Welcome @Bandylegged on StackOverflow, It would really help others if you can attached some code snippet. For more detail on how to write good answer please visit stackoverflow.com/help/how-to-answerRoast
W
0

Make sure that the selected cell is in the right "module" and if necessary, inherit:

enter image description here

If not, your IBOutlets will be nil.

Weapon answered 27/4, 2021 at 16:29 Comment(0)
S
-1

Issue I was facing: TableViewCell has been created and all the IBOutlets are nil. So I can't set any values such as text or color etc. Below code worked for me.

Xcode version: 13.3

Step 1: Remove datasource and delegate reference form storyboard.

Step 2: In viewDidLoad add,

tableView.delegate = self
tableView.dataSource = self

Step 3: In tableview UITableViewDataSource cellForRowAt function, add your cell the given way.

let cell = tableView.dequeueCell(ofType: YourCellName.self)
cell.yourCellFunction()
return cell

Note 1: dequeueCell(ofType...) is calling the below function internally. you don't need to use it directly.

func dequeueCell<T: UITableViewCell>(ofType type: T.Type) -> T  {
}

Important: You don't need to provide any "Resporation ID" or "Reuse Identifier" for cell. It works with your cell name.

Shala answered 3/8, 2022 at 20:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.