Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Missing return UITableViewCell

I am sure this question have been asked before but I can't find an answer that solves my problem with nested if-else and switch-case logic.
I have a UITableView with two sections, each sections has two custom cells. That is it it. 4 cells. But no matter what I do I get "Missing return in a function expected to return UITableViewCell"

Question How can I change this setup so that I get an else statement at the bottom that will satisfy swift logic?

Any help would be very much appreciated

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

    if indexPath.section == 0{

        switch (indexPath.row) {
        case 0:
            let cell0: SettingsCell! = tableView.dequeueReusableCellWithIdentifier("cell0", forIndexPath: indexPath) as! SettingsCell
        cell0.backgroundColor = UIColor.redColor()
        break

        case 1:
            let cell1: SettingsCell! = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! SettingsCell
        cell1.backgroundColor = UIColor.whiteColor()
         break

        default:
            break
        }
    }

    if indexPath.section == 1{

        switch (indexPath.row) {
        case 0:
            let cell10: SettingsCell! = tableView.dequeueReusableCellWithIdentifier("cell10", forIndexPath: indexPath) as! SettingsCell
        cell10.backgroundColor = UIColor.redColor()
        break

        case 1:
            let cell11: SettingsCell! = tableView.dequeueReusableCellWithIdentifier("cell11", forIndexPath: indexPath) as! SettingsCell
        cell11.backgroundColor = UIColor.whiteColor()
         break

        default:
            break

        }
    }
}
like image 378
KML Avatar asked May 12 '15 11:05

KML


1 Answers

  • Declare the cell at the start of the method,
  • assign a value to the cell depending on section and row number,
  • throw a fatalError() in all cases that "should not occur",
  • return the cell.

Also note that the break statements are not needed. The default behavior in Swift is not to fall through to the next case.

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

    let cell: SettingsCell

    switch(indexPath.section) {
    case 0:
        switch (indexPath.row) {
        case 0:
            cell = tableView.dequeueReusableCellWithIdentifier("cell0", forIndexPath: indexPath) as! SettingsCell
            cell.backgroundColor = UIColor.redColor()

        case 1:
            cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! SettingsCell
            cell.backgroundColor = UIColor.whiteColor()

        default:
            fatalError("Unexpected row \(indexPath.row) in section \(indexPath.section)")
        }
    case 1:
        switch (indexPath.row) {
        case 0:
            cell = tableView.dequeueReusableCellWithIdentifier("cell10", forIndexPath: indexPath) as! SettingsCell
            cell.backgroundColor = UIColor.redColor()

        case 1:
            cell = tableView.dequeueReusableCellWithIdentifier("cell11", forIndexPath: indexPath) as! SettingsCell
            cell.backgroundColor = UIColor.whiteColor()

        default:
            fatalError("Unexpected row \(indexPath.row) in section \(indexPath.section)")

        }
    default:
        fatalError("Unexpected section \(indexPath.section)")

    }
    return cell
}

The fatalError() error function is marked as @noreturn, so the compiler knows that program execution will not continue from the default cases. (This also helps to find logic errors in the program.)

The compiler verifies that a value is assigned to cell in all other cases.

The possibility to initialize a constant (let cell ...) in this way is new in Swift 1.2.


Alternatively, you can create a cell and return it "immediately" in each case:

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

    switch(indexPath.section) {
    case 0:
        switch (indexPath.row) {
        case 0:
            let cell = tableView.dequeueReusableCellWithIdentifier("cell0", forIndexPath: indexPath) as! SettingsCell
            cell.backgroundColor = UIColor.redColor()
            return cell

        case 1:
            let cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! SettingsCell
            cell.backgroundColor = UIColor.whiteColor()
            return cell

        default:
            fatalError("Unexpected row \(indexPath.row) in section \(indexPath.section)")
        }
    case 1:
        switch (indexPath.row) {
        case 0:
            let cell = tableView.dequeueReusableCellWithIdentifier("cell10", forIndexPath: indexPath) as! SettingsCell
            cell.backgroundColor = UIColor.redColor()
            return cell

        case 1:
            let cell = tableView.dequeueReusableCellWithIdentifier("cell11", forIndexPath: indexPath) as! SettingsCell
            cell.backgroundColor = UIColor.whiteColor()
            return cell

        default:
            fatalError("Unexpected row \(indexPath.row) in section \(indexPath.section)")

        }
    default:
        fatalError("Unexpected section \(indexPath.section)")
    }
}

Again, calling fatalError() solves the "missing return expected" compiler error.

This pattern can be useful if there are different kinds of cells (with different classes) created in each case.

like image 100
Martin R Avatar answered Oct 11 '22 01:10

Martin R