5

I'm having trouble creating custom table view cells in swift with Xcode6 (beta 4). More precisely I'm unable to access (unwrap) my custom UILabels inside the cell, since they never gets initialized.

Here's how I've got it all setup:

I've made a view in storyboard, which contains a table view with a prototype cell:

How it looks in storyboard

The view is hooked up to a class MyCoursesTableViewController, and the cell (with identifier courseCell) to CourseTableViewCell. I've pasted both classes below (with just the relevant bits of code):

MyCoursesTableViewController.swift

import UIKit

class MyCoursesTableViewController: NavToggleTableViewController {

    override func viewDidLoad() {
       super.viewDidLoad()

        self.tableView.registerClass(CourseTableViewCell.self, forCellReuseIdentifier: "courseCell")
    }

    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! {

        var cell : CourseTableViewCell = tableView.dequeueReusableCellWithIdentifier("courseCell", forIndexPath: indexPath) as CourseTableViewCell

        // cell is not nil

        if let titleLabel = cell.titleLabel {
            // never gets here
        } else {
            cell.textLabel.text = "Course Title"
        }

        return cell
    }
}

The NavToggleTableViewController class is just a common baseclass I use for all view controllers and doesn't affect the result.

CourseTableViewCell.swift

import UIKit

class CourseTableViewCell: UITableViewCell {

    @IBOutlet weak var courseIcon: UIImageView!
    @IBOutlet weak var teacherIcon: UIImageView!
    @IBOutlet weak var studentsCountIcon: UIImageView!
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var studentsCountLabel: UILabel!
    @IBOutlet weak var teacherLabel: UILabel!

    init(style: UITableViewCellStyle, reuseIdentifier: String!) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    }

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

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

Below is a picture of how I've configured the cell in the utilities pane (in storyboard):

Utilities Pane

The problem arise inside the function tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> CourseTableViewCell when I want to access the UILabels. If I were to put something like cell.titleLabel.text = "Course Title" I get the following error message:

fatal error: unexpectedly found nil while unwrapping an Optional value

Where am I doing things wrong? Would appreciate any help, thanks!

tobiasandersen
  • 8,480
  • 3
  • 28
  • 39

2 Answers2

0

As explained in the last answer in UITableView Using Swift , it is an Xcode bug. Add the following:

    override func tableView(tableView:UITableView!, heightForRowAtIndexPath indexPath:NSIndexPath)->CGFloat {
    return 44
}

(or whatever height you want) and you'll be ok. I duplicated your code and verified the solution.

Apologies, I forgot something else: you must not registerClass:forCellReuseIdentifier. This is already done when you set up your table and prototype cell in interface builder.

Community
  • 1
  • 1
Rikkles
  • 3,372
  • 1
  • 18
  • 24
  • Thanks for the suggestion, but I just tried it with the same result as before. Would you mind sharing your code? – tobiasandersen Aug 09 '14 at 11:51
  • 2
    Sorry, forgot to add you must not use registerClass. What this will do is completely recreate a prototype cell in code, disconnecting your IB prototype cell from your code. So your issues were twofold, one of them being an Xcode bug. – Rikkles Aug 09 '14 at 13:18
0

Sorry to reply after so much time has passed but I tear my hair on this exact problem this whole weekend. This bug is still there on XCode 8.3.2 (8E2002), this is the latest one as I write these lines. I had the exact same problem as the OP and adding

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 44
}

did not worked for me. The only thing that worked for me was removing this from my viewDidLoad:

    override func viewDidLoad() {
    super.viewDidLoad()

    // Uncomment the following line to preserve selection between presentations
    // self.clearsSelectionOnViewWillAppear = false

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem()


    // REMOVE THIS v v v v v        
    self.tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "MyCustomCell")
    // REMOVE THIS ^ ^ ^ ^ ^ 
    // Do whatever you want here…
}

The heightForRowAt indexPath is ineffective, you don't need to use it to fix it.

I hope this helped someone too !

Samuel Prevost
  • 1,047
  • 1
  • 11
  • 30