Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create two table views in one view controller with two custom UITableViewCells?

Tags:

ios

swift

I am trying to create two UITableViews in one view controller using two custom UITableViewCells. I have the following:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    if tableView == self.tableView {
        let cell = tableView.dequeueReusableCellWithIdentifier("CustomOne") as! CustomOneTableViewCell
        return cell
    }

    if tableView == self.autoSuggestTableView {
        let cell = tableView.dequeueReusableCellWithIdentifier("CustomTwo") as! CustomTwoTableViewCell
        return cell
    }
}

But I keep getting the error:

Missing return in a function expected to return 'UITableViewCell'

What do I have to return in the end of the method?

like image 265
butter_baby Avatar asked May 25 '16 20:05

butter_baby


Video Answer


6 Answers

The error appears because if for any reason, the table view is non of the two options that you wrote, then it doesn't have any value to return, just add a default value at the end:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if tableView == firstTableView,
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomOne") as? CustomOneTableViewCell {
        return cell
    } else if tableView == autoSuggestTableView,
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTwo") as? CustomTwoTableViewCell {
        return cell
    }

    return UITableViewCell()
}

Updated to swift 4.1.2: I've updated this answer to version 4.1.2, also, because the return value of the method cannot be nil, modified to a default, dummy UITableViewCell.

like image 169
Fantini Avatar answered Oct 05 '22 04:10

Fantini


Your issue is that the compiler looks at the possibility that both if statements might be false and you don't return anything in that case, hence the error.

If you only have the two tables, the easiest change is this:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    if tableView == self.tableView {
        let cell = tableView.dequeueReusableCellWithIdentifier("CustomOne") as! CustomOneTableViewCell
        return cell
    } else {
        let cell = tableView.dequeueReusableCellWithIdentifier("CustomTwo") as! CustomTwoTableViewCell
        return cell
    }
}
like image 43
rmaddy Avatar answered Oct 05 '22 03:10

rmaddy


My preferred solution to this problem would be to do the following:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cellToReturn = UITableViewCell() // Dummy value
    if tableView == self.tableView {
        let cell = tableView.dequeueReusableCellWithIdentifier("CustomOne") as! CustomOneTableViewCell
        cellToReturn = cell
    } else if tableView == self.autoSuggestTableView {
        let cell = tableView.dequeueReusableCellWithIdentifier("CustomTwo") as! CustomTwoTableViewCell
        cellToReturn = cell
    }

    return cellToReturn
}

I think this method maintains readability and clarity whilst also solving the error. I don't like having (dangerous) code written only for compatibility like return nil.

like image 26
Benjamin Lowry Avatar answered Oct 05 '22 05:10

Benjamin Lowry


If you try two or more than two table in ViewController.then you must be identify tableView in all delegates and dataSource methods. for example

extension ViewController: UITableViewDataSource {

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return tableView == firstTableView ? first.count: second.count
        //return second.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        var returnCell = UITableViewCell()
        if tableView == firstTableView {
            let cell = tableView.dequeueReusableCell(withIdentifier: "firstCell", for: indexPath)
            cell.textLabel?.text = first[indexPath.row]
            returnCell = cell
        } else {
            let cell = tableView.dequeueReusableCell(withIdentifier: "secondCell", for: indexPath)
            cell.textLabel?.text = second[indexPath.row]
            returnCell = cell
        }
        return returnCell
    }
}
like image 38
Rakesh Kunwar Avatar answered Oct 05 '22 03:10

Rakesh Kunwar


Building off of Fantini's answer, I would suggest using a switch statement to clean it up a bit:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

  switch tableView {

    case firstTableView:
      let cell = tableView.dequeueReusableCell(withIdentifier: "CustomOne") as? CustomOneTableViewCell {
      return cell

    case autoSuggestTableView:
      let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTwo") as? CustomTwoTableViewCell {
      return cell

    default:
      return UITableViewCell()
  }
}

Just in case you plan on adding more tableView's later.

like image 39
BaxiaMashia Avatar answered Oct 05 '22 03:10

BaxiaMashia


import UIKit

class ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource {

@IBOutlet weak var topTableView: UITableView!
@IBOutlet weak var downTableview: UITableView!
var topData : [String] = []
var downData = [String]()

override func viewDidLoad() {
    super.viewDidLoad()

    topTableView.delegate = self
    downTableview.delegate = self
    topTableView.dataSource = self
    downTableview.dataSource = self

    for index in 0...20 {
        topData.append("Top Table Row \(index)")
    }

    for index in 10...45 {
        downData.append("Down Table Row \(index)")
    }

}

func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    var numberOfRow = 1
    switch tableView {
    case topTableView:
        numberOfRow = topData.count
    case downTableview:
        numberOfRow = downData.count
    default:
        print("Some things Wrong!!")
    }
    return numberOfRow
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell = UITableViewCell()
    switch tableView {
    case topTableView:
        cell = tableView.dequeueReusableCell(withIdentifier: "topCell", for: indexPath)
        cell.textLabel?.text = topData[indexPath.row]
        cell.backgroundColor = UIColor.green
    case downTableview:
        cell = tableView.dequeueReusableCell(withIdentifier: "downCell", for: indexPath)
        cell.textLabel?.text = downData[indexPath.row]
        cell.backgroundColor = UIColor.yellow
    default:
        print("Some things Wrong!!")
    }
    return cell
}

}

like image 25
zaid afzal Avatar answered Oct 05 '22 05:10

zaid afzal