soleil
soleil

Reputation: 13073

Simple UITableView in Swift - unexpectedly found nil

Pretty simple code:

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

func tableView(tableView:UITableView!, numberOfRowsInSection section:Int) -> Int {
    return 5
}


func tableView(tableView:UITableView!, cellForRowAtIndexPath indexPath:NSIndexPath!) -> UITableViewCell! {
    let cell: BookTableViewCell = BookTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "BookCell")
    println("ip: \(indexPath.row)")
    cell.bookLabel.text = "test"

    return cell
}

On the cell.bookLabel.text line I get this:

fatal error: unexpectedly found nil while unwrapping an Optional value

The BookTableViewCell is defined like this:

class BookTableViewCell: UITableViewCell {

    @IBOutlet var bookLabel: UILabel

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

And bookLabel is correctly hooked up in a Prototype cell in the Storyboard. Why am I getting this error?

Upvotes: 17

Views: 34061

Answers (13)

Kratos
Kratos

Reputation: 84

Swift 5 In same storyboard two class are there Class A and Class B, Class B contains tableview outlet, when i tried to push Class A to Class B it's crashed and show tableView outlet nil.

In class A i did navigation like below code.

let classBObj = ClassB()
self.navigationController?.pushViewController(classBObj, animated: true)

Then i realised my mistake and used below code and it's work perfectly.

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let classBObj = storyboard.instantiateViewController(withIdentifier: "ClassB") as! ClassB
self.navigationController?.pushViewController(classBObj, animated: true)

Upvotes: 2

swiftBoy
swiftBoy

Reputation: 35783

You need to check two things

1. Register cell with nib name in viewDidLoad


func viewDidLoad() 
{
    super.viewDidLoad()
    listTableView.register(UINib.init(nibName: "ListProductCell", bundle: nil), forCellReuseIdentifier: "ListProductCell")
 }

2. Create custom cell this way.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ListProductCell") as! ListProductCell
        return cell
    }

Upvotes: 3

ABS
ABS

Reputation: 7732

In Swift 5

First I tried registering my UITableViewCell in viewdidload() using class and identifier which I have mentioned below but it did not work for me.

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

Solution

Then I registered my UITableViewCell using Nib name and it worked for me

Register your cell in viewdidload() using Nib name

override func viewDidLoad() 
{
    super.viewDidLoad()
    // Do any additional setup after loading the view.

    //register your table view cell in Viewdidload() using Nib Name       
    tableView.register(UINib.init(nibName: "MyCustomTableViewCell", bundle: nil), forCellReuseIdentifier: "customCell")
}

Upvotes: 0

Alex Bailey
Alex Bailey

Reputation: 793

The reason why this question gets asked a lot is because it depends on how you setup your tableview and custom CellClass. Do you create your tableview in storyboard or programmatically? Do you create custom .xib Cells and custom Cell classes?

If you created your tableview programmatically and created custom .xib and Cell class here is the answer for Swift 4:

in viewDidLoad:

        customTable.register(UINib(nibName: "NibName", bundle: nil), forCellReuseIdentifier: "NibNameIdentifier")

in cellforRowat:
        let cell = tableView.dequeueReusableCell(withIdentifier: "NibName") as! ClassName

Note: In your cell .xib file make sure you set your identifier in the Attributes inspector ("NibNameIdentifier").

Upvotes: 3

Photon Point
Photon Point

Reputation: 808

I encounter this error, if I put UITapGestureRecognizer in a custom UITableViewCell on the storyboard.(Xcode version is 8.3).

Upvotes: 0

Darius Miliauskas
Darius Miliauskas

Reputation: 3504

Do not forget to register nib (tested with Swift3), e. g. inside override func viewDidLoad():

self.tableView.register(UINib(nibName: "BookTableViewCell", bundle: nil), forCellReuseIdentifier: "BookCell")

Upvotes: 3

Dania Delbani
Dania Delbani

Reputation: 826

I am getting this error whenever I use reuse Identifer name different than the custom class name unifid those names solve it for me

Upvotes: 0

Brigadier
Brigadier

Reputation: 896

Try doing this:

let cell = tableView.dequeueReusableCellWithIdentifier("BookCell", forIndexPath: indexPath) as! BookTableViewCell

and don't forget to set the reuse identifier in your storyboard

Upvotes: 1

Dani.Rangelov
Dani.Rangelov

Reputation: 366

In my case it was the way the Optional is unwrapped:

let cellId:String = "ConverterTableCell"
let cell: ConverterTableViewCell = (tableView.dequeueReusableCellWithIdentifier(cellId)! as? ConverterTableViewCell)!

Upvotes: 1

Hieu Vo
Hieu Vo

Reputation: 3274

Possibly that your view in Main.Storyboard lost its IBOutlet reference in ViewController file, just link it again.

Upvotes: 9

Gerard G
Gerard G

Reputation: 3463

I was getting this error because I didn't have the identifier written in the Storyboard of the Custom Cell.

StoryBoard

Also make sure it matches you code in:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
    {

        let cell = tableView.dequeueReusableCellWithIdentifier("CustomTableCell") as CustomTableCell

        ...
    }

Upvotes: 20

mliu
mliu

Reputation: 1737

If you're using storyboard, make sure you don't have this line at the start of your file:

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

It will overwrite the storyboard and as a result, the outlet links in the storyboard are ignored.

Upvotes: 85

Nate Cook
Nate Cook

Reputation: 93276

When you create a view in code, its IBOutlet properties don't get hooked up properly. You want the version that you get back from dequeueReusableCellWithIdentifier:

let cell = tableView.dequeueReusableCellWithIdentifier("BookCell") as BookTableViewCell

Upvotes: 7

Related Questions