61

我正在努力弄清楚这个代码片段有什么问题。这目前在 Objective-C 中有效,但在 Swift 中,这只是在方法的第一行崩溃。它在控制台日志中显示一条错误消息:Bad_Instruction

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

        if (cell == nil) {
            cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "Cell")
        }

        cell.textLabel.text = "TEXT"
        cell.detailTextLabel.text = "DETAIL TEXT"

        return cell
    }
4

17 回答 17

82

另请参阅马特的答案,其中包含解决方案的后半部分

让我们在不创建自定义子类或 nib 的情况下找到解决方案

真正的问题在于 Swift 区分可以为空的nil对象 ( ) 和不能为空的对象。如果您没有为您的标识符注册 nib,则dequeueReusableCellWithIdentifier可以返回nil.

这意味着我们必须将变量声明为可选:

var cell : UITableViewCell?

我们必须使用as?notas

//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
于 2014-06-04T09:48:05.480 回答
64

Sulthan 的回答很聪明,但真正的解决方案是:不要调用dequeueReusableCellWithIdentifier. 那是你一开始的错误。

这种方法已经完全过时了,我很惊讶它还没有被正式弃用;任何可以容纳 Swift(iOS 7 或 iOS 8)的系统都不需要它用于任何目的。

相反,调用现代方法,dequeueReusableCellWithIdentifier:forIndexPath:. 这样做的好处是不涉及任何选项;您保证将返回一个单元格。所有的问号和感叹号都消失了,您可以使用let代替,var因为细胞的存在是有保证的,并且您生活在一个方便的现代世界中。

如果您不使用情节提要,则必须事先为该标识符注册表格,注册一个类或一个 nib。执行此操作的常规位置是viewDidLoad,早在 table view 存在时。

这是一个使用自定义单元类的示例:

override func viewDidLoad() {
    super.viewDidLoad()
    self.tableView.registerClass(MyCell.self, forCellReuseIdentifier: "Cell")
}

// ...

override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath:indexPath) as MyCell
    // no "if" - the cell is guaranteed to exist
    // ... do stuff to the cell here ...
    cell.textLabel.text = // ... whatever
    // ...
    return cell
}

但是,如果您使用的是故事板(大多数人都这样做),您甚至不需要在viewDidLoad! 只需在情节提要中输入单元格标识符,您就可以使用dequeueReusableCellWithIdentifier:forIndexPath:.

于 2014-07-23T14:18:52.630 回答
18

@Sulthan 的回答很到位。一种可能的方便修改是将单元格转换为 UITableViewCell!,而不是 UITableViewCell。

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
    var cell = tableView.dequeueReusableCellWithIdentifier("CELL") as UITableViewCell!
    if !cell {
        cell = UITableViewCell(style:.Default, reuseIdentifier: "CELL")
    }
    // setup cell without force unwrapping it
    cell.textLabel.text = "Swift"
    return cell
}

现在,您可以修改单元格变量,而无需每次都强制解包。使用隐式展开的选项时要小心。您必须确定您正在访问的值是有价值的。

有关更多信息,请参阅The Swift Programming Language的“隐式解包选项”部分。

于 2014-06-15T22:10:21.157 回答
8

这是我写的让它工作的东西......

首先将表格视图单元格注册到表格视图中

self.tableView.registerClass(MyTableViewCell.self, forCellReuseIdentifier: "Cell")

然后配置 cellForRowAtIndexPath

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

    cell.textLabel.text = "Cell Text"
    cell.detailTextLabel.text = "Cell Detail Text in Value 1 Style"

    return cell
}

然后我在文件底部定义了一个自定义单元子类写入(因为它现在容易多了)

class MyTableViewCell : UITableViewCell {

    init(style: UITableViewCellStyle, reuseIdentifier: String!) {
        super.init(style: UITableViewCellStyle.Value1, reuseIdentifier: reuseIdentifier)
    }

}
于 2014-06-04T03:38:41.063 回答
8

尝试这个:

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
    cell.textLabel.text = "\(indexPath.row)"

    return cell
}

请注意,您应该UITableViewCell在创建实例化时注册您和 ID UITableView

tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: "Cell")
于 2014-06-03T18:55:05.423 回答
6

这是在swift 2中定义表格单元格的简单方法:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let identifier = "cell"
    let cell = tableView.dequeueReusableCellWithIdentifier(identifier) ??
        UITableViewCell.init(style: UITableViewCellStyle.Default, reuseIdentifier: identifier)
    cell.textLabel!.text = "my text"
    return cell
}

斯威夫特 3:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let identifier = "cell"
    let cell = tableView.dequeueReusableCell(withIdentifier: identifier) ??
        UITableViewCell(style: .default, reuseIdentifier: identifier)
    cell.textLabel!.text = "my text"
    return cell
}
于 2016-02-23T23:59:14.820 回答
4

这里有一些答案,但我认为它们中的任何一个都不是理想的,因为在声明之后你会得到一个可选的 UITableViewCell,然后cell!...在任何声明中都需要一个。我认为这是一种更好的方法(我可以确认它在 Xcode 6.1 上编译):

var cell:UITableViewCell

if let c = tableView.dequeueReusableCellWithIdentifier("cell") as? UITableViewCell {
    cell = c
}
else {
    cell = UITableViewCell()
}
于 2014-10-27T06:12:11.423 回答
2

好吧,我已经这样做了:

使用Swift的UITableView的步骤:

  • ViewController中取UITableView
  • ViewController.swift类中提供引用插座
  • 将Outlets数据源委托ViewController

现在ViewController.swift类中的Swift代码:

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var mTableView: UITableView!

    var items: [String] = ["Item 1","Item 2","Item 3", "Item 4", "Item 5"]

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.mTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

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

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var cell:UITableViewCell = self.mTableView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell

        cell.textLabel?.text = self.items[indexPath.row]
         println(self.items[indexPath.row])

        return cell
    }

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

现在是时候运行你的程序了。

完毕

于 2015-08-02T14:23:11.333 回答
1

实际上,在 Apple 的 TableView Guide 文档和示例代码中,您会发现以下语句:

如果 dequeueReusableCellWithIdentifier: 方法要求一个在故事板中定义的单元格,该方法总是返回一个有效的单元格。如果没有等待重用的回收单元,则该方法使用情节提要本身中的信息创建一个新单元。这消除了检查 nil 的返回值并手动创建单元格的需要。

所以,我们可以这样编码:

var identifer: String = "myCell"
var cell = tableView.dequeueReusableCellWithIdentifier(identifer) as UITableViewCell
cell.textLabel.text = a[indexPath.row].name
cell.detailTextLabel.text = "detail"

我认为这是使用 tableView 的合适方式

于 2014-09-01T02:44:06.540 回答
1

使用“as”关键字将执行以下两个步骤:
1.创建一个包装 UITableViewCell 变量的可选值;
2.unwrapping可选值。

所以,通过这样做

var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Component") as UITableViewCell

你会得到一个“普通”的 UITableViewCell 类型变量:cell。从理论上讲,这样做是可以的。但是下一行

if (cell == nil) {}

很麻烦,因为在swift中,只有可选值可以用nil赋值。

所以,要解决这个问题,你必须让 cell 成为 Optional 类型的变量。像这样:

var cell = tableView.dequeueReusableCellWithIdentifier("Component") as? UITableViewCell

使用关键字“as?” 将创建一个 Optional 变量,毫无疑问,它可以用 nil 赋值。

于 2015-01-16T06:28:46.253 回答
0

对于单元格模板:

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
        让 myCell : youCell = youCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
        返回我的细胞
    }
于 2014-06-04T09:33:53.303 回答
0

兄弟,请看一下示例https://github.com/brotchie/SwiftTableView

于 2014-06-07T09:32:08.747 回答
0

为什么不是这个?

(如果我不在目标中,请删除...)

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

    if let cell: UITableViewCell = theTableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as? UITableViewCell {
        // cell ok
    }else{
       // not ok
    }
}
于 2014-09-01T17:36:19.663 回答
0

使用 Playground 的 UITableView 演示

//: 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
于 2017-05-29T09:43:06.760 回答
0

我已经通过以下方式完成:显示detailTextLabel。文本值

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

    let CellIdentifier: String = "cell"

    var cell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier) as? UITableViewCell

    if cell == nil {
        cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: CellIdentifier)
    }

    //cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator

    // parse the value of records
    let dataRecord = self.paymentData[indexPath.row] as! NSDictionary

    let receiverName = dataRecord["receiver_name"] as! String
    let profession = dataRecord["profession"] as! String
    let dateCreated = dataRecord["date_created"] as! String
    let payAmount = dataRecord["pay_amount"] as! String

    println("payment \(payAmount)")
    cell!.textLabel?.text = "\(receiverName)\n\(profession)\n\(dateCreated)"
    cell!.detailTextLabel?.text = "$\(payAmount)"
    cell!.textLabel?.numberOfLines = 4

    return cell!

}// end tableview
于 2015-07-30T12:46:38.493 回答
0

我浏览了您的代码,很可能崩溃的原因是您试图对未分配的可选值进行类型转换

现在考虑下面的代码行

var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell

当表格视图中没有单元格时,您仍在尝试将类型转换为 UITableView。当编译器尝试对 nil 值进行类型转换时,您将面临此问题

正确的说法应该是

var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") 

您可以使用 if else 语句对持有的值进行类型转换

于 2017-06-06T07:20:25.777 回答
-3

试试这个代码

var cell:CustomTableViewCell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCell") as CustomTableViewCell
cell.cellTitle.text="vijay"

https://github.com/iappvk/TableView-Swift

于 2014-08-21T12:29:14.033 回答