Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

Custom UITableView Cell is Causing An Error

My app is a simple RSS Reader that uses a tableview to display the list of articles. In order to display a picture from each of the articles in a tableview cell as well as the title and author of the articles, I used a custom UITableViewCell. I made a class for the tableview cell and created outlets for the imageview and labels from a prototype cell in the storyboard to the class. The code for my custom tableview cell is as follows:

import UIKit

class itemTableViewCell: UITableViewCell {

@IBOutlet weak var itemTitleLabel: UILabel!
@IBOutlet weak var itemImageView: UIImageView!
@IBOutlet weak var itemAuthorLabel: UILabel!
class var reuseIdentifier: String {
    get {
        return "cell"
    }
}
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
}

}

Furthermore, in my UITableViewController, I have the following code for the cellForRowAtIndexPath method:

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


    let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath:  
indexPath) as! itemTableViewCell

 let item = feedItems[indexPath.row] as MWFeedItem

   cell.itemImageView.image = UIImage(named: "placeholder")
    cell.backgroundColor = UIColor.clearColor()


    cell.itemAuthorLabel.text = item.author
    cell.itemTitleLabel.text = item.title




    if item.content != nil {

        let htmlContent = item.content as NSString
        var imageSource = ""

        let rangeOfString = NSMakeRange(0, htmlContent.length)
        let regex = try? NSRegularExpression(pattern: "(<img.*?src=\")(.*?)(\".*?>)", options: 
[])

        if htmlContent.length > 0 {
            let match = regex?.firstMatchInString(htmlContent as String, options: [], range: 
rangeOfString)

            if match != nil {
                let imageURL = htmlContent.substringWithRange(match!.rangeAtIndex(2)) as
 NSString
                print(imageURL)

                if NSString(string: 
imageURL.lowercaseString).rangeOfString("feedburner").location == NSNotFound {
                    imageSource = imageURL as String

                }

            }
        }

        if imageSource != "" {
            cell.itemImageView.setImageWithURL(NSURL(string: imageSource)!, 
placeholderImage: UIImage(named: "placeholder"))
        }
        else{
            cell.itemImageView.image = UIImage(named: "placeholder")
        }

    }
    return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath:  
 NSIndexPath) {

    let item = feedItems[indexPath.row] as MWFeedItem

    let webBrowser = KINWebBrowserViewController()
    let url = NSURL(string: item.link)

    webBrowser.loadURL(url)


    self.navigationController?.pushViewController(webBrowser, animated: true)
}

Whenever I run the app, I get the following error: 'unable to dequeue a cell with identifier cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard.' I do not understand this as I thought that if a custom cell was created in the storyboard you did not need to register a nib or class.

Any help is greatly appreciated and sorry for this extremely long post!

3 Answers

First of all, please change the class name class itemTableViewCell: UITableViewCell to uppercase. Every time someone creates a class name without capitalizing the first char, a unicorn dies. ;)

If you have and linked up this cell in Interface Builder, you might want to set the reuse identifier there as well. If you are doing this programmatically, try registering the class of your custom cell upfront in viewDidLoad for example, just to give you an idea. This could look like this:

// Untested
tableView.registerClass(ItemTableViewCell.self, forCellReuseIdentifier: ItemTableViewCell.reuseIdentifier)

Hope that helps :)

I typed that in as self.tableView.registerClass(itemTableViewCell.self, forCellReuseIdentifier: itemTableViewCell().reuseIdentifier!) and got the error: "fatal error: unexpectedly found nil while unwrapping an Optional value" over that line.

As reuseIdentifier is a class method rather than an instance method, you have to call it like this: ItemTableViewCell.reuseIdentifier. Rename your table view cell to ItemTableViewCellfirst. Then use the code I have posted above.

I did that and then I got the error: 'unable to dequeue a cell with identifier ItemTableViewCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard.' I appreciate you sticking with me to solve this problem!

Ok, so did you create your table view in Storyboard and have you added the cell there as well? If so, go to Interface Builder, select your cell in the overview on the left and open the Utilities bar (upper right). There, select the Identity Inspector and make sure "Custom Class" is set to "ItemTableViewCell". Then select the Attributes Inspector and make sure that the identifier is set to "cell". If that's the case you should be able to dequeue this cell without further customization. For the sake of this test, let's don't use the class method of your cell, but simply use the String "cell" for your identifier.

Let me know if that helps :)

I did that and got a different error of : "fatal error: unexpectedly found nil while unwrapping an Optional value" over the line:

 cell.itemImageView.image = UIImage(named: "placeholder")

Note that I do have an image named "placeholder" in my xcassets folder so that isn't the issue.

Thanks again for all of your suggestions.

fatal error: unexpectedly found nil while unwrapping an Optional value

These errors are easily avoided. Don't ever force unwrap something you are in control of with !. Instead, make sure you do fully understand the concept of optionals. use guard, if let and/or optional chaining. You can learn all about it in the Apple Docs: Optionals.

Here is an example:

// Make sure the cell exists
guard let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath:  
indexPath) as? ItemTableViewCell else {
    fatalError("Could not dequeue cell!")
}

// Make sure the image exists
if let image = UIImage(named: "placeholder") {
   cell.itemImageView.image = image
} else {
   print("No image found")
}

What I did to fix all of this is I just customized the cell programmatically via the cell's backgroundView and didn't use a custom tableview cell class. Thank you for your suggestions though.