所以我正在为 UITableView 创建一些 View 模型。表格有不同的单元格类型,所以我使用了泛型,但是将它们放入数组时出现了一些问题。
首先我定义了一个结构体:
private struct Section<E, C> where C: UITableViewCell {
let cell: C.Type
let rows: [E]
let configure: (_ row: E, _ cell: inout C, _ index: Int) -> Void
}
然后我声明了一个数组:
private lazy var sections: [Any] = [
Section(cell: TextFieldTableViewCell.self,
rows: [
TableRow(image: R.image.home.device.settings.name(),
title: R.string.localizable.deviceSettingsViewControllerElementDeviceName(),
content: device.name,
action: { _ in
}),
TableRow(image: R.image.home.device.settings.location(),
title: R.string.localizable.deviceSettingsViewControllerElementDeviceLocation(),
content: device.location,
action: { _ in
})],
configure: { row, cell, index in
}),
Section(cell: DeviceSettingsNightVisionTableViewCell.self,
rows: [
TableRow(image: R.image.home.device.settings.nightVision(),
title: R.string.localizable.deviceSettingsViewControllerElementNightVision(),
content: 0,
action: { _ in
})],
configure: { row, cell, index in
})
]
问题是:
- 我无法指定数组的类型,因为它们实际上是不同的泛型。
- 如果我使用
[Any]
作为数组的类型,那么每次取一个元素,我都必须将其转换为对应的类型,这与我最初的设计不一致。 - 我做了一些搜索,意识到我可能需要使用协议(protocol)来解决问题,但我尝试了很多次都失败了。
我期望的结果是,当我取一个元素时,我可以在不进行转换的情况下正确获取它的类型。
我目前的做法是这样的:
在 numberOfRowsInSection:
中,
switch section {
case 0:
return (self.sections[section] as! Section<TableRow, TextFieldTableViewCell>).rows.count
case 1:
return (self.sections[section] as! Section<TableRow, DeviceSettingsNightVisionTableViewCell>).rows.count
default:
return 0
}
显然不够优雅,请问是否有更好的解决方案,任何帮助或建议都非常感谢。
最佳答案
您可以为您的行对象使用协议(protocol),并使用标识符而不是类型,我不完全确定这会完全解决您的问题,但您可以尝试一下:
protocol CellProtocol where Self: UITableViewCell {
func bind(_ object: RowProtocol)
}
protocol RowProtocol {
}
struct Row1: RowProtocol {
}
struct Row2: RowProtocol {
}
private struct Section {
let cellIdentifier: String
let rows: [RowProtocol]
let configure: (_ row: RowProtocol, _ cell: inout UITableViewCell, _ index: Int) -> Void
}
private lazy var sections: [Section] = [
Section(cellIdentifier: "cell1",
rows: [Row1()],
configure: { row, cell, index in
}),
Section(cellIdentifier: "cell2",
rows: [Row2()],
configure: { row, cell, index in
})
]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: sections[indexPath.section].cellIdentifier, for: indexPath) as? CellProtocol {
cell.bind(sections[indexPath.section].rows[indexPath.row])
}
}
让你自定义的cell类符合CellProtocol
,然后在bind
函数里面,尝试将RowProtocol
转换成Row1
或 Row2
获取它们的值。
我也不确定您将如何在该部分对象内部进行配置,感觉不对,我宁愿让单元格类自行处理配置。
关于ios - 数组中的 Swift 不同类型的泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51392762/