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 }
但是,如果你使用的是一个故事板(大多数人都这样做),你甚至不需要在viewDidLoad
registry视图! 只要在故事板中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 }
为什么不呢?
(如果我不在目标中,请删除)
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"
- iOS 8 Map Kit Obj-C无法获取用户位置
- 如何在Xcode 6(iOS 8)模拟器上使用Charles Proxy?
- Xcode 6 – 如何为Ad-Hoc分发select签名证书/configuration文件?
- 仅在iPhone 6 iOS 8模拟器上显示黑色文本的状态栏
- ios8中的Safari是固定的元素获得焦点时的滚动屏幕
- iOS库到BitCode
- 错误:日志目录不存在/ var / mobile / Library / Logs / CrashReporter / DiagnosticLog /
- 禁用UITextField预测文本
- 在iOS 8.0.0 GM Safari上通过HTTP上传文件失败