55

Consider the following simple view controller:

class ViewController: UIViewController, UITableViewDataSource { @IBOutlet weak var tableView: UITableView! var items = ["One", "Two", "Three"] override func viewDidLoad() { super.viewDidLoad() self.tableView.registerClass(CustomTableViewCell.self, forCellReuseIdentifier: "customCell") self.tableView.dataSource = self } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.items.count; } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = self.tableView.dequeueReusableCellWithIdentifier("customCell") as CustomTableViewCell cell.titleLabel!.text = self.items[indexPath.row] return cell } } 

And custom cell view:

class CustomTableViewCell: UITableViewCell { @IBOutlet weak var titleLabel: UILabel! } 

This code causes the following error.

fatal error: unexpectedly found nil while unwrapping an Optional value

titleLabel is nil — it's not clear why. Setting default properties of UITableViewCell (like textLabel) work just fine.

I'm using a nib for the custom cell.

Both the labels and table views are correctly connected to their IBOutlets.

label table view

Both the prototype cell and the custom nib view are marked as having a CustomTableViewCell class.

I'm new to iOS development, am I missing something obvious?

Sample Xcode project available.

11
  • Is the cell here not nil? (let cell = self.tableView.dequeueReusableCellWithIdentifier("customCell") as CustomTableViewCell) Commented Mar 17, 2015 at 14:05
  • You noticed the warning "/Main.storyboard:64: Prototype table cells must have reuse identifiers"? Commented Mar 17, 2015 at 14:06
  • @ThomasKilian Adding a reuse identifier in the Attributes inspector removes the warning but does not affect the issue. Commented Mar 17, 2015 at 14:13
  • @iOSfleer cell is not nil. For example, setting the cell's textLabel property causes the label to correctly appear in the UI. Commented Mar 17, 2015 at 14:16
  • 13
    If you've made your cell in a xib file, you should register the nib, not the class (only register the class if the cell's subviews are created in code). Commented Mar 17, 2015 at 14:58

6 Answers 6

62

First off, you're using a nib file to load your custom cell into the table. That's probably going to be more of a headache than it's worth if you're new to Swift/Cocoa. I would move everything over to storyboard for the time being. Instead of using a nib file click, go to Storyboard, click on your UITableView and make sure the TableView's content setting is Dyanamic Prototypes:

enter image description here

Next, click on the prototype cell (the only one in the table view) and set the class to CustomTableViewCell and set its reuse identifier to customCell:

enter image description here enter image description here

Next, add a label to your prototype cell and link it to the IBOutlet in your CustomTableViewCell class. You don't need to register your customCell so long as you've set the reuse identifier in storyboard. Delete this line:

self.tableView.registerClass(CustomTableViewCell.self, forCellReuseIdentifier: "customCell") 

and it should run.

Sign up to request clarification or add additional context in comments.

11 Comments

I've commented out that line, the issue is still present. (there are no warnings and the reuse identifier is correctly set in the attributes inspector)
Oh I see, you're using a nib for your CustomViewCell. You need to mention that in the question of it's misleading. Is there any reason you have for not just generating the cell in storyboard?
I was coding the "register" and setting the reuse ID storyboard. This consistently returned NIL properties of the custom-cell (e.g., "label", "imageview", etc.). When I removed the register coding, it works as expected.
The key is here is to link the cell view on the storyboard with reuse identifier and remove the line collectionView.register(...)
That's not a good answer because it doesn't answer the question. I don't want to know how do to it that way. I want to know how to do it the way the questioner asked, without being told 'it's a bad idea because I'm new to Swift.' I don't care about that. Who green checks these things when they don't answer the question?
|
44

try this

import UIKit class ViewController: UIViewController, UITableViewDataSource { @IBOutlet weak var tableView: UITableView! var items = ["One", "Two", "Three"] override func viewDidLoad() { super.viewDidLoad() self.tableView.registerNib(UINib(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "customCell")// CustomTableViewCell.self, forCellReuseIdentifier: "customCell") self.tableView.dataSource = self } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.items.count; } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = self.tableView.dequeueReusableCellWithIdentifier("customCell", forIndexPath: indexPath) as CustomTableViewCell cell.titleLabel!.text = self.items[indexPath.row] return cell } } 

4 Comments

This seems like the issue. Thank you.
This is the obvious answer here. Since you are building your cell on a Nib, then you have to register that cell using the appropriate method. registerNib rather than registerClass...
Been looking for this solution for hours
This is the proper answer. It addresses the poster's issue directly.
12

Register your nib like this:

let bundle = Bundle(for: type(of: self)) let nib = UINib(nibName: "PickerCell", bundle: bundle) collectionViewPicker.register(nib, forCellWithReuseIdentifier: "cell") 

1 Comment

It works fine for me as well. Instead of collectionViewPicker you have to use your tableView object!
6

You should use dequeueReusableCellWithIdentifier:forIndexPath to dequeue the cells.

If you are using storyboard to create the cells, you should not need to register the class for reuse as storyboard does it for you if you set the reuseIdentifier.

5 Comments

That doesn't fix it, same issue. I've updated the sample XCode project in the question with your suggestion.
Have you got self.tableView.delegate = self anywhere? Seems to be missing in viewDidLoad? You assign the dataSource delegate but not the delegate?
Just looked at your source. You have no delegate as mentioned above and no methods for heightForRowAtIndexPath etc... This will not be helping things.
I tried pulling the smallest subset of code that would replicate the issue from my main project. I do have the rest of the plumbing in my real project — is there any indication that these things are causing the issue? They're present in my main project.
Not if they are present in the main code. Just noticed they were missing. Only other suggestion is what happens if you remove the "weak" statement from the IBOutlet?
1

Please make sure you are not doing any mistake while registering your nib(custom cell) in the viewdidload. Nib name and reuseIdentifiers should not be wrong.

Comments

-10

Works for me without !

EDIT

 let challenge = self.challenges![indexPath.row] let title = challenge["name"] if title != nil { cell.titleLabel.text = title } 

2 Comments

What's title? Clearly just checking for nil will work, but that skirts the issue entirely.
It was just a sample, i edited my post to understand.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.