Milap
Milap

Reputation: 145

Swift: Customizing TableView to hold multiple columns of data

So I'm customizing a tableview to hold multiple columns. I want 3 columns, and am customizing the TableViewCell, except I'm at a roadblock.

Right now I have a TableView that is in a ViewController, and the TableView accurately holds one column of data. Here I am changing it to three columns and I get an error about unwrapping an optional nil value.

Here's the important parts of viewcontroller with the tableview (FinishTestController.swift):

    var bestRank: [String] = ["1", "2", "3", "4", "5"]
var bestScore: [String] = ["-----", "-----", "-----", "-----", "-----"]
var bestTime: [String] = ["-----", "-----", "-----", "-----", "-----"]
override func viewDidLoad() {
    super.viewDidLoad()

    addhighscore()
    loadhighscores()

    self.tableView.registerClass(TableViewCell.self, forCellReuseIdentifier: "cell")
}

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

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return bestRank.count;;
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! TableViewCell

    cell.column1.text = self.bestRank[indexPath.row]//<-- ERROR points here
    cell.column2.text = self.bestScore[indexPath.row]
    cell.column2.text = self.bestTime[indexPath.row]

    return cell
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    println("You selected cell #\(indexPath.row)!")
}

func loadhighscores(){
    var result = db.query("SELECT * from EASY_MATH5 ORDER BY Score DESC, Time ASC LIMIT 5", parameters: nil)
    println("===============================")

    for row in result
    {
        bestScore[i] = row["Score"]!.asString()
        print(bestScore[i])
        bestTime[i] = row["Time"]!.asString()
        println(bestTime[i])

        i++
    }
}

Here's my cell:

class TableViewCell: UITableViewCell {

@IBOutlet weak var column1: UILabel!
@IBOutlet weak var column2: UILabel!
@IBOutlet weak var column3: UILabel!


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
}

}

And here's the error I get:

fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)

and points to the line that says "cell.column1.text = self.bestRank[indexPath.row]" with a line "Thread 1: EXC_BAD_INSTRUCTION".

Any idea on how to resolve?

Upvotes: 0

Views: 8262

Answers (3)

devim1
devim1

Reputation: 532

Using your code I made minor adjustments which I've noted in the comments with "// nb: " - it works fine now - once those minor points were removed.

Only other change in my code that I did, was the use of "Cell1" instead of "cell" and name of custom cell as "CustomTableViewCell" instead of "TableViewCell", but this is only from personal habit.

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet var tableView: UITableView!

var bestRank : [String] = ["1", "2", "3", "4", "5"]
var bestScore: [String] = ["-----", "-----", "-----", "-----", "-----"]
var bestTime: [String] = ["-----", "-----", "-----", "-----", "-----"]

// --------------------------------------
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.bestRank.count  // nb: use of "self." and no ";;" at end
}

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

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell1", forIndexPath: indexPath) as! CustomTableViewCell

    cell.column1.text = self.bestRank[indexPath.row]
    cell.column2.text = self.bestScore[indexPath.row]
    cell.column3.text = self.bestTime[indexPath.row]

    return cell
}

// --------------------------------------
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    print("You selected cell #\(indexPath.row)!")
}
// --------------------------------------

override func viewDidLoad() {
    super.viewDidLoad()

    // nb: Not used: "self.tableView.registerClass(TableViewCell.self, forCellReuseIdentifier: "cell")"

// nb: Datasource + delegate already assigned with tableview in storyboard with click-drag-drop into ViewController. }


CustomCell was done like yours...

class CustomTableViewCell: UITableViewCell {

@IBOutlet var column1: UILabel!

@IBOutlet var column2: UILabel!

@IBOutlet var column3: UILabel!

** Results = No Error ** Simulator showing table as you wanted...

enter image description here

Upvotes: 0

beyowulf
beyowulf

Reputation: 15331

Remove

self.tableView.registerClass(TableViewCell.self, forCellReuseIdentifier: "cell")

From viewDidLoad(), you don't need to register your UITableViewCell subclass if you're using prototype cells.

Upvotes: 2

JoshR604
JoshR604

Reputation: 155

You should most likely be using a UICollectionView for this type of behaviour.

With a collection view you will have more control of the layout of each cell.

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICollectionView_class/

Upvotes: -1

Related Questions