I\'m struggling to figure out what\'s wrong with this code snippet. This is currently working in Objective-C, but in Swift this just crashes on the first line of the method.
Try this:
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel.text = "\(indexPath.row)"
return cell
}
Note that you should register you UITableViewCell
and ID when creating instantiating your UITableView
:
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: "Cell")
There's a few answers here, but I don't think any of them are ideal, because after the declaration you're ending up with an optional UITableViewCell, which then needs a cell!...
in any declarations. I think this is a better approach (I can confirm this compiles on Xcode 6.1):
var cell:UITableViewCell
if let c = tableView.dequeueReusableCellWithIdentifier("cell") as? UITableViewCell {
cell = c
}
else {
cell = UITableViewCell()
}
bro, please take a look at the sample https://github.com/brotchie/SwiftTableView
UITableView Demo using Playground
//: Playground - noun: a place where people can play
import UIKit
import PlaygroundSupport
class TableviewDemoDelegate:NSObject,UITableViewDataSource,UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell:UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath as IndexPath)
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
}
cell?.textLabel?.text = "Item \(indexPath.row+1)"
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You have selected cell #\(indexPath.row)!")
}
}
var tableView = UITableView(frame:CGRect(x: 0, y: 0, width: 320, height: 568), style: .plain)
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
let delegate = TableviewDemoDelegate()
tableView.delegate = delegate
tableView.dataSource = delegate
PlaygroundPage.current.liveView = tableView
Also see matt's answer which contains the second half of the solution
Let's find a solution without creating custom subclasses or nibs
The real problem is in the fact that Swift distinguishes between objects that can be empty (nil
) and objects that can't be empty. If you don't register a nib for your identifier, then dequeueReusableCellWithIdentifier
can return nil
.
That means we have to declare the variable as optional:
var cell : UITableViewCell?
and we have to cast using as?
not as
//variable type is inferred
var cell = tableView.dequeueReusableCellWithIdentifier("CELL") as? UITableViewCell
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "CELL")
}
// we know that cell is not empty now so we use ! to force unwrapping but you could also define cell as
// let cell = (tableView.dequeue... as? UITableViewCell) ?? UITableViewCell(style: ...)
cell!.textLabel.text = "Baking Soda"
cell!.detailTextLabel.text = "1/2 cup"
cell!.textLabel.text = "Hello World"
return cell