[英]How can I use an if statement to set a type of variable to a specific type of custom tableCell?
I have three different types of custom UITableCells. 我有三种不同类型的自定义UITableCells。 I have an if statement that sets them up: 我有一个if语句来设置它们:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if somePosts[indexPath.row].typeOfPost == .linkPost {
let cell: LinkTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "linkTableViewCell") as! LinkTableViewCell
} else if somePosts[indexPath.row].typeOfPost == .picturePost {
let cell: PictureTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "pictureTableViewCell") as! PictureTableViewCell
} else if somePosts[indexPath.row].typeOfPost == .textPost {
let cell: TextTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "textTableViewCell") as! TextTableViewCell
} else {
print("Type of post is not link, picture, or text")
}
}
Each of the custom cells has similar labels such as title and time. 每个自定义单元格都有类似的标签,例如标题和时间。 I would like to set these labels using the same line of code, such as: 我想使用同一行代码来设置这些标签,例如:
cell.titleLabel.text = "Some title here"
However, in this example, I get an error saying I am using an unresolved identifier "cell," obviously because my variables are being declared non-globally. 但是,在此示例中,我收到一条错误消息,指出我使用的是未解析的标识符“单元格”,这显然是因为我的变量是非全局声明的。 Is there a way around this since swift is strongly typed? 由于swift是强类型的,是否有办法解决? Thanks! 谢谢!
Make a protocol that your TableViewCell classes extend, and store cell
as a variable of that type. 制定一个协议,以供TableViewCell类扩展,并将cell
存储为该类型的变量。
protocol MyTableViewCell {
var titleLabel: UILabel { get }
// ...
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let identifier: String
switch somePosts[indexPath.row].typeOfPost {
case .linkPost: identifier = "linkTableViewCell"
case .picturePost: identifier = "pictureTableViewCell"
case .textPost: identifier = "textTableViewCell"
default: fatalError("Type of post is not link, picture, or text")
}
guard let cell = self.tableView.dequeueReusableCell(withIdentifier: identifier) as? MyTableViewCell else {
fatalError("Cell isn't castable to MyTableViewCell")
}
cell.titleLabel.text = "Some title here"
// ...
}
You have three basic solutions. 您有三个基本解决方案。
cell.text = ...
inside each block. 在每个块内重复cell.text = ...
But this isn't what you really want as stated in your question. 但是,这并不是您所提问题中真正想要的。 For options 2 and 3 you would declare a variable of the base/protocol type before the first if
statement. 对于选项2和3,您将在第一个if
语句之前声明基本/协议类型的变量。 Then after the whole if/else
block, you can assign any of the common properties. 然后,在整个if/else
块之后,可以分配任何公共属性。
If you need to update any cell type specific properties, you can do that inside the appropriate block as well. 如果需要更新任何特定于单元格类型的属性,则也可以在适当的块内执行此操作。
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell: BaseTableViewCell?
if somePosts[indexPath.row].typeOfPost == .linkPost {
cell = self.tableView.dequeueReusableCell(withIdentifier: "linkTableViewCell") as! LinkTableViewCell
} else if somePosts[indexPath.row].typeOfPost == .picturePost {
cell = self.tableView.dequeueReusableCell(withIdentifier: "pictureTableViewCell") as! PictureTableViewCell
} else if somePosts[indexPath.row].typeOfPost == .textPost {
cell = self.tableView.dequeueReusableCell(withIdentifier: "textTableViewCell") as! TextTableViewCell
} else {
print("Type of post is not link, picture, or text")
}
if let cell = cell {
cell.commonProperty = ...
return cell
} else {
return nil // this shouldn't happen but if it does, you have a bug to fix
}
}
If the subclasses each have their own titleLabel property, you will need to make them all conform to a protocol. 如果每个子类都有自己的titleLabel属性,则需要使它们全部符合协议。 Let's call it ConfigurableCell
. 我们称之为ConfigurableCell
。
protocol ConfigurableCell {
var titleLabel: UILabel { get set }
}
Then, you can initialize your cells all the same way, but declare them as a ConfigurableCell
: 然后,您可以用相同的方式初始化单元,但是将它们声明为ConfigurableCell
:
var cell: ConfigurableCell? = nil // not set yet
if somePosts[indexPath.row].typeOfPost == .linkPost {
cell = self.tableView.dequeueReusableCell(withIdentifier: "linkTableViewCell") as! LinkTableViewCell
} else if somePosts[indexPath.row].typeOfPost == .picturePost {
cell = self.tableView.dequeueReusableCell(withIdentifier: "pictureTableViewCell") as! PictureTableViewCell
} else if somePosts[indexPath.row].typeOfPost == .textPost {
cell = self.tableView.dequeueReusableCell(withIdentifier: "textTableViewCell") as! TextTableViewCell
}
guard let cell = cell else {
// how to handle this error case is up to you
print("Type of post is not link, picture, or text")
return UITableViewCell()
}
// now, cell is a ConfigurableCell with a titleLabel property, regardless of class
cell.titleLabel.text = "Some title"
Of course, UITableViewCell
does have a built-in textLabel
property, which you could try to utilize in your cell classes, and then a protocol wouldn't be necessary, because the property is in UITableViewCell
. 当然, UITableViewCell
确实具有内置的textLabel
属性,您可以尝试在单元格类中使用该属性,然后不需要协议,因为该属性位于UITableViewCell
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.