Ios 如何使用if语句将变量类型设置为特定类型的自定义tableCell?
我有三种不同类型的自定义UITableCell。我有一个if语句来设置它们:Ios 如何使用if语句将变量类型设置为特定类型的自定义tableCell?,ios,swift,uitableview,protocols,Ios,Swift,Uitableview,Protocols,我有三种不同类型的自定义UITableCell。我有一个if语句来设置它们: override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if somePosts[indexPath.row].typeOfPost == .linkPost { let cell: LinkTableV
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")
}
}
每个自定义单元格都有类似的标签,如标题和时间。我希望使用同一行代码设置这些标签,例如:
cell.titleLabel.text = "Some title here"
然而,在这个例子中,我得到一个错误,说我使用了一个未解析的标识符“cell”,显然是因为我的变量被声明为非全局的。既然swift是强类型的,有没有办法解决这个问题?谢谢 您有三个基本解决方案
cell.text=…
。但这并不是你在问题中所说的你真正想要的if
语句之前声明一个基本/协议类型的变量。然后在整个if/else
块之后,可以指定任何公共属性
如果需要更新任何特定于单元类型的属性,也可以在相应的块内进行更新
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
}
}
如果每个子类都有自己的titleLabel属性,则需要使它们都符合协议。我们称之为
ConfigurableCell
protocol ConfigurableCell {
var titleLabel: UILabel { get set }
}
然后,您可以以相同的方式初始化单元格,但将其声明为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"
当然,
UITableViewCell
确实有一个内置的textLabel
属性,您可以尝试在单元格类中使用该属性,然后就不需要协议了,因为该属性位于UITableViewCell
中,它可以创建一个协议供TableViewCell类扩展,并将单元格
存储为该类型的变量
protocol ConfigurableCell {
var titleLabel: UILabel { get set }
}
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"
// ...
}
不相关,但从数据源数组中三次检索该类型的代价是不必要的。您应该使用switch语句
switch-somePosts[indexPath.row].typeOfPost{case.linkPost…
谢谢,这很有帮助。我对这一点很陌生,所以任何建议都会受到重视这里有这么多重复的代码。停止疯狂。除了瓦迪安说的以外?所有建议都会受到重视;我不是最好的编码员。让我更好!@有人看到我对亚历山大答案的评论。他们会帮助你更好地理解波菲,我是新手,所以如果这是一个愚蠢的问题,请不要杀了我,但是当我声明协议时,我得到了一个错误:“协议中的属性必须有显式的{get}或{get set}说明符。好吧,这修复了这个错误,但是现在我得到了“无法将类型“LinkTableViewCell”(以及所有其他类型的单元格)的值分配给类型ConfigurableCell?”?“您是否使类符合协议?class-LinkTableViewCell:UITableViewCell,ConfigurableCell{…
您需要添加协议一致性(直接或通过扩展)对于所有的表格单元格类型。我强烈建议阅读全文,因为这是理解如何编写好的Swift代码的最重要部分之一。好吧,我真的很烂,我提前道歉。它一直在第二行出现致命错误。但不确定为什么…所有标签都必须相同吗?有些不同nt和一些在每个自定义单元格中都是相同的。我试着这样做,这样相同的就不需要多次键入。@有人忘记让现有类符合这个新协议了吗?@Honey 0。我怀疑他没有创建他的类(LinkTableViewCell
,TextTableViewCell
,等等)符合MyTableViewCell。1.是的,协议确实需要一个更好的名称,但我对问题域的了解还不够,无法提出建议。2.是的,他的类应该符合此协议,以便能够引用这些类的实例作为MyTableViewCell
,而不考虑它们的具体类型。3。也许,如果该按钮是协议的逻辑部分。4.苹果公司对此有一个视频。@Honey 5.这是必要的,以便向编译器表示,无论具体类型是什么(LinkTableViewCell
,Text…
,Picture…
)是一个实例,我们可以始终确保它将是一个具有标题标签的类型,我们可以使用该类型,而不必关心该类型的任何其他细节。@亲爱的,假设协议不存在,而cell
具有类型NSTableViewCell
。我们在这里处理的所有实例都可以分配给cell
。但是,当我们说cell.titleLabel
时,编译器会给出一个错误。NSTableViewCell
没有titleLabel
,因此不能保证实例的具体类型有titleLabel
。协议形式化地保证titleLabel
将为存在单元格
,无论其具体类型如何。