我正在使用自定义单元格构建自定义UITableView
。
每个自定义单元格都是FormItemTableViewCell
我正在尝试填充cellForRowAtIndexPath
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = FormItemTableViewCell();
if(indexPath.row == 1){
cell = tableView.dequeueReusableCellWithIdentifier(twoOptionCellIdentifier, forIndexPath: indexPath) as! TwoOptionTableViewCell
} else {
cell = tableView.dequeueReusableCellWithIdentifier(oneTextFieldCellIdentifier, forIndexPath: indexPath) as! OneTextFieldTableViewCell
}
cell.questionLabel.text = "What is the meaning of life?";
return cell
}
如何访问子类中的元素?
例如:TwoOptionTableViewCell
有一个segControl
而OneTextFieldTableViewCell
有一个answerTextField
答案 0 :(得分:3)
您可以使用以下两种方法之一:
1)最好的方法:
if(indexPath.row == 1) {
let cell = tableView.dequeueReusableCellWithIdentifier(twoOptionCellIdentifier, forIndexPath: indexPath) as! TwoOptionTableViewCell
// the type of cell is TwoOptionTableViewCell. Configure it here.
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier(oneTextFieldCellIdentifier, forIndexPath: indexPath) as! OneTextFieldTableViewCell
// the type of cell is TwoOptionTableViewCell. Configure it here.
return cell
}
2)如果你只宣称cell
一次,作为一个超类,那么你必须像这样向下转发它。
var cell: FormItemTableViewCell
cell = ... // dequeue and assign the cell like you do in your code.
if let twoOptionCell = cell as? TwoOptionTableViewCell
{
// configure twoOptionCell
}
else if let oneTextFieldCell = cell as? OneTextFieldTableViewCell
{
// configure oneTextFieldCell
}
return cell
一旦添加代码以使单元格出列,这就更加详细了。所以我个人更喜欢并推荐第一种方法。
答案 1 :(得分:3)
在这个问题中有一些不错的答案,但是大多数都有一个共同的坏事,他们强制解包的选项,你应该尽可能多地避免(几乎唯一可以接受的地方使用它们在IBOutlets中)
我认为这是解决这个问题的最佳方法:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCellWithIdentifier("Identifier", forIndexPath: indexPath) as? FormItemTableViewCell else {
fatalError("Cell is not of kind FormItemTableViewCell")
}
switch cell {
case let cell as TwoOptionTableViewCell where indexPath.row == 1:
// Configure cell, which is an object of class TwoOptionTableViewCell, but only when we are in row 1
break
case let cell as TwoOptionTableViewCell:
// Configure cell, which is an object of class TwoOptionTableViewCell, when the row is anything but 1
break
case let cell as OneTextFieldTableViewCell:
// Configure cell, which is an object of class OneTextFieldTableViewCell
break
case _: print("The cell \(cell) didn't match any patterns: \(indexPath)")
}
cell.questionLabel.text = "What is the meaning of life?";
return cell
}
现在让我向您介绍我认为最好的方式。
首先,它并没有强制解开任何选项,所有内容都在switch
案例中很好地解开。
它将您的单元格从表格中取消(您应该经常这样做),并确保它是FormItemTableViewCell
的子类,否则会引发致命错误。
通过使用switch case,它会将cell
转换为您需要的类,同时它会检查它是否是您想要的索引路径。因此,如果要在共享类的不同行中共享某些逻辑,则可以将indexPath.row
与多个值进行比较。如果您不使用where
子句,它将在找到该类的单元格的所有位置使用相同的逻辑。
请注意,您需要添加一些逻辑以根据行获取所需的标识符。
答案 2 :(得分:1)
如果我理解正确,您希望将单元格的主要声明保留为reshape2
以访问公共属性。
您可以创建一个新变量并为其指定演变版本。 用这个实例做你的东西,因为这是一个类对象,它将指向相同的引用。
FormItemTableViewCell
答案 3 :(得分:0)
在这种情况下你必须有条件地施放它们。我喜欢使用Enums for Rows / Sections而不是== 1
(取决于你的TableView设置方式),但基本上你想要做以下事情:
if indexPath.row == 1 {
let cell = tableView.dequeueReusableCellWithIdentifier(twoOptionCellIdentifier, forIndexPath: indexPath) as! TwoOptionTableViewCell
// Note that we cast the cell to TwoOptionTableViewCell
// access `segControl` here
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier(oneTextFieldCellIdentifier, forIndexPath: indexPath) as! OneTextFieldTableViewCell
// This cell we cast to OneTextFieldTableViewCell.
// access `answerTextField` here
return cell
}
您正在做的是将单元格定义为FormItemTableViewCell
,因此后续访问只会在该表单中知道它,即使您在赋值期间将其明确地转换为子类。
作为旁注,您不必像在那里那样分配到var
,您可以做的是let cell: FormItemTableViewCell
。然后在if语句中,您可以定义子类的新单元格,对它们进行操作,然后分配回原始cell
,然后返回它。如果您要在if语句之后对两种单元格类型执行相同的操作(例如设置背景颜色或其他内容,而不管您拥有哪个子类),这将非常有用。
以下是我最喜欢处理这种情况的方法:
enum CellTypes {
case TwoOption, OneTextField
init(row: Int) {
if row == 1 {
self = .TwoOption
} else {
self = .OneTextField
}
}
var reuseIdentifier: String {
switch self {
case .TwoOption: return "twoOptionReuseIdentifier"
case .OneTextField: return "oneTextFieldReuseIdentifier"
}
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: FormItemTableViewCell
let cellType = CellTypes(row: indexPath.row)
switch cellType {
case .TwoOption:
let twoOptionCell = tableView.dequeueReusableCellWithIdentifier(cellType.reuseIdentifier, forIndexPath: indexPath) as! TwoOptionTableViewCell
// do stuff with the `segControl`
cell = twoOptionCell
case .OneTextField:
let textFieldCell = tableView.dequeueReusableCellWithIdentifier(cellType.reuseIdentifier, forIndexPath: indexPath) as! OneTextFieldTableViewCell
// do stuff with the `answerTextField`
cell = textFieldCell
}
// Here do something regardless of which CellType it is:
cell.questionLabel.text = "What is the meaning of life?"
return cell
}