Swift tableView.dequeueReusableCell Never Returning Nil

15,145

You don't need to check if the cell is nil using this dequeue method, as long as you've register a cell class for reuse, or provided a prototype in Interface Builder.

let cell = tableView.dequeueReusableCellWithIdentifier("CellSubtitle", forIndexPath: indexPath) as! UITableViewCell

If however, you want to continue manually initializing the cells, you can use the following dequeue method instead. (keep in mind, this is the old way)

let cell = tableView.dequeueReusableCellWithIdentifier("CellSubtitle") as? UITableViewCell

Then as far as initializing the detailTextLabel goes, you don't have to. It's built into the cell, and by specifying that the cell's style should be subtitle, that label will be set up for you.

Note that the casts aren't necessary in Swift 2.

Share:
15,145
Jacob
Author by

Jacob

Software Engineer at MediaBrains, Inc. Carnegie Mellon University Information Systems, C/O 2020

Updated on June 09, 2022

Comments

  • Jacob
    Jacob almost 2 years

    This is my Swift code to generate my table view. I am trying to set up a tableView with detail labels. The problem is that the following code is never called.

    if (cell == nil) {
                println("1")
                cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "CellSubtitle")
                //cell = tableViewCell
            }
    

    Here is the code you need for the method:

        func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
    {
        println("start TableViewCellForRowAtIndexPath")
        var cell: UITableViewCell! = tableView.dequeueReusableCellWithIdentifier("CellSubtitle", forIndexPath: indexPath) as UITableViewCell
        if (cell == nil) {
            println("1")
            cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "CellSubtitle")
            //cell = tableViewCell
        }
    
        cell.textLabel.text = instructions[indexPath.row].text
        println("2")
        //cell.detailTextLabel
        cell.detailTextLabel.text = "HI"
        println("3")
    

    Here is the console output for the method:

    start load
    1
    2
    done load
    start TableViewCellForRowAtIndexPath
    2
    fatal error: Can't unwrap Optional.None
    (lldb) 
    

    How can I initialize the detailTextLabel in order to insert text? When I try to set the text for the label, I receive

    fatal error: Can't unwrap Optional.None. 
    

    Why am I receiving this error?

  • Jacob
    Jacob almost 10 years
    Please see the updated question. Even after changing the method like you stated, when I set text to to detailTableView I still receive the error fatal error: Can't unwrap Optional.None
  • Mick MacCallum
    Mick MacCallum almost 10 years
    @jbman223 What kind of objects are you storing in your instructions array?
  • Jacob
    Jacob almost 10 years
    the instructions are a custom object to hold data for the text, detail text, and image, and other information.
  • rdelmar
    rdelmar almost 10 years
    The second way you show, using the older dequeue method will also not ever return a nil cell if the cell is made in the storyboard (assuming that the identifier is correct).
  • Roi Mulia
    Roi Mulia almost 9 years
    lol funny you updated the question a hour ago. If i want to initialize the cell only once for certain properties, like border width, how can i check using your method if he already initialized , and not do the same thing every time?
  • Mick MacCallum
    Mick MacCallum almost 9 years
    @roimulia Typically what you would do in this situation is use with first of these two methods, and move your setup code into the initializer (or layoutSubviews/etc what ever is appropriate) in a UITableViewCell subclass. That way, the code will only be executed once (in the case of init) for each cell that the table determines it needs. It has to make enough of them to exhaust your data source, or fill the table's bounds (which ever comes first).
  • Roi Mulia
    Roi Mulia almost 9 years
    So generally move this to the cell subclass? :)
  • Mick MacCallum
    Mick MacCallum almost 9 years
    @roimulia When possible yes. It will help keep the code organized. Of course you'll need to keep logic for things like pulling data out of your datasource in cellForRowAtIndexPath/willDisplayCell/etc.
  • Roi Mulia
    Roi Mulia almost 9 years
    Thanks! Is it the same behavior if for instance i want to put an image view inside cell? because when i tried doing this only from cellforrowatindexpath it started duplicated(because if the reuse) lol
  • Mick MacCallum
    Mick MacCallum almost 9 years
    @roimulia Well it depends. If you have a single image that will be displayed in all the cells, it's better to move that work into the cell's initializer. However, if the image will be different depending on the indexPath, you'll want to keep the logic in cellForRowAtIndexPath, but in that case you need to make sure to reset properties where appropriate. For example, if some cells should have images, but others shouldn't you need to explicitly set imageView.image to nil in the cases where no image should be shown, because of the cell reuse.
  • Roi Mulia
    Roi Mulia almost 9 years
    Starting to get it :) so in the case of different images depends on the cell index, this imageView will be the "outlet" from the cell subclass or i will only declare it only in the cellForRowAtIndexPath?
  • Roi Mulia
    Roi Mulia almost 9 years
    I tied doing that, didnt work so well. Im trying to put an image only 3 cells out of 10(for example), should i create a ImnageView from cellforindexpath or create it in the subclass?
  • scord
    scord almost 9 years
    cell is never nil here.