我正在努力弄清楚这段代码的错误.这目前在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 }
Sulthan.. 82
另请参阅matt的答案,其中包含解决方案的后半部分
让我们找到一个解决方案,而无需创建自定义子类或nib
真正的问题在于Swift区分了可以为empty(nil
)的对象和不能为空的对象.如果您没有为标识符注册nib,则dequeueReusableCellWithIdentifier
可以返回nil
.
这意味着我们必须将变量声明为可选:
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
matt.. 63
Sulthan的答案很聪明,但真正的解决方案是:不要打电话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
!只需在故事板中输入单元格标识符即可dequeueReusableCellWithIdentifier:forIndexPath:
.
另请参阅matt的答案,其中包含解决方案的后半部分
让我们找到一个解决方案,而无需创建自定义子类或nib
真正的问题在于Swift区分了可以为empty(nil
)的对象和不能为空的对象.如果您没有为标识符注册nib,则dequeueReusableCellWithIdentifier
可以返回nil
.
这意味着我们必须将变量声明为可选:
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
试试这个:
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")
Sulthan的答案很聪明,但真正的解决方案是:不要打电话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
!只需在故事板中输入单元格标识符即可dequeueReusableCellWithIdentifier:forIndexPath:
.
@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 }
现在,您可以修改单元格变量,而不必每次都强行展开它.使用隐式展开的选项时要小心.您必须确定您访问的值具有值.
有关更多信息,请参阅Swift编程语言的"隐式解包选项"部分.
以下是我为了让它正常工作所写的内容......
首先使用表视图注册表视图单元格
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) } }
这是在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 }