UITableView在Swift中

我正在努力弄清楚这个代码片段有什么问题。 这目前在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 } 

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

让我们find一个解决scheme,而不创build自定义的子类或笔尖

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

这意味着我们必须声明variables是可选的:

 var cell : UITableViewCell? 

我们必须使用as? 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 

苏丹的答案很聪明,但真正的解决scheme是: 不要调用dequeueReusableCellWithIdentifier 。 那是你一开始的错误。

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

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

如果不使用故事板,则必须事先在表中注册该标识符,注册类或笔尖。 传统的做法是viewDidLoad ,它早在表视图就存在。

以下是使用自定义单元类的示例:

 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 } 

但是,如果你使用的是一个故事板(大多数人都这样做),你甚至不需要在viewDidLoadregistry视图! 只要在故事板中input单元格标识符,就可以使用dequeueReusableCellWithIdentifier:forIndexPath:

@苏丹的答案是现货。 一个可能的方便修改是将单元格转换为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 } 

现在,您可以修改单元格variables,而不必每次都解压。 使用隐式解包选项时要小心。 您必须确定您正在访问的值有一个值。

有关更多信息,请参阅Swift编程语言的“Implicitly Unwrapped Optionals”部分。

尝试这个:

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

请注意,在创build实例化你的UITableView时,你应该注册你的UITableViewCell和ID:

 tableView.delegate = self tableView.dataSource = self tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: "Cell") 

这是我写的让它工作的

首先用表格视图registry格视图单元格

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

然后configurationcellForRowAtIndexPath

 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) } } 

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

 var cell:UITableViewCell if let c = tableView.dequeueReusableCellWithIdentifier("cell") as? UITableViewCell { cell = c } else { cell = UITableViewCell() } 

这里是一个简单的方法来定义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 } 

Swift 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 } 

那么,我已经这样做了:

使用Swift的 UITableView的步骤:

  • ViewController中使用 UITableView
  • ViewController.swift类中提供引用出口
  • 给Outlet 数据源委托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)!") } } 

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

完成

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

如果dequeueReusableCellWithIdentifier:方法要求在故事板中定义的单元格,则此方法始终返回有效的单元格。 如果没有等待重复使用的再循环单元,则该方法使用故事板本身中的信息创build新的单元。 这样就不需要检查nil的返回值并手动创build一个单元格。

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

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

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

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

所以,这样做

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

你会得到一个“普通的”UITableViewCelltypes的variables:cell。理论上讲,可以这样做。但是下一行

 if (cell == nil) {} 

麻烦,因为在迅速,只有可选的值可以分配为零。

所以,要解决这个问题,你必须把单元格变成一个可选types的variables。 像这样:

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

使用关键字“as?” 会创build一个可选variables,毫无疑问,这可以被赋予nil。

对于单元格模板:

  func tableView(tableView:UITableView !, cellForRowAtIndexPath indexPath:NSIndexPath!) - > UITableViewCell!  {
         let myCell:youCell = youCell(style:UITableViewCellStyle.Subtitle,reuseIdentifier:“cell”)
        返回myCell
     }

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

为什么不呢?

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

 func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { if let cell: UITableViewCell = theTableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as? UITableViewCell { // cell ok }else{ // not ok } } 

我按照以下方式完成:显示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 

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 

我经历了你的代码,很可能是崩溃的原因是你正在试图指定一个未分配的可选值

现在考虑下面的代码行

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

当tableview中没有单元格的时候,你仍然试图将types转换为UITableView。当编译器试图改写nil值时,你会遇到这个问题

正确的说法应该是

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

您可以使用if语句来对包含的值进行types转换

试试这个代码

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

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