Представьте, что ваши данные будут такими:
class TableViewModel {
let items: [Any] = [
User(name: "John Smith", imageName: "user3"),
"Hi, this is a message text. Tra la la. Tra la la.",
Bundle.main.url(forResource: "beach@2x", withExtension: "jpg")!,
User(name: "Jessica Wood", imageName: "user2"),
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
]
}
Поэтому обычно мы реализуем его в методе tableView(_:cellForRowAt:)
со многими if let ...
Один из способов предотвратить это - использовать универсальные типы. Общее программирование - отличный способ избежать стандартного кода и помогает определять ошибки во время компиляции.
Общий код позволяет вам писать гибкие, многократно используемые функции и
типы, которые могут работать с любым типом, с учетом требований, которые вы
определить. Вы можете написать код, который избегает дублирования и выражает его
намерение в ясной, отвлеченной манере.
Документация Apple
Давайте составим первый протокол, которому должна соответствовать каждая ячейка.
protocol ConfigurableCell {
associatedtype DataType
func configure(data: DataType)
}
//example of UserCell
class UserCell: UITableViewCell, ConfigurableCell {
@IBOutlet weak var avatarView: UIImageView!
@IBOutlet weak var userNameLabel: UILabel!
func configure(data user: User) {
avatarView.image = UIImage(named: user.imageName)
userNameLabel.text = user.name
}
}
Теперь мы можем создать универсальный конфигуратор ячеек, который будет настраивать ячейки нашей таблицы.
protocol CellConfigurator {
static var reuseId: String { get }
func configure(cell: UIView)
}
class TableCellConfigurator<CellType: ConfigurableCell, DataType>: CellConfigurator where CellType.DataType == DataType, CellType: UITableViewCell {
static var reuseId: String { return String(describing: CellType.self) }
let item: DataType
init(item: DataType) {
self.item = item
}
func configure(cell: UIView) {
(cell as! CellType).configure(data: item)
}
}
Теперь нам нужны некоторые корректировки нашей ViewModel:
typealias UserCellConfigurator = TableCellConfigurator<UserCell, User>
typealias MessageCellConfigurator = TableCellConfigurator<MessageCell, String>
typealias ImageCellConfigurator = TableCellConfigurator<ImageCell, URL>
class TableViewModel {
let items: [CellConfigurator] = [
UserCellConfigurator(item: User(name: "John Smith", imageName: "user3")),
MessageCellConfigurator(item: "Hi, this is a message text. Tra la la. Tra la la."),
ImageCellConfigurator(item: Bundle.main.url(forResource: "beach@2x", withExtension: "jpg")!),
UserCellConfigurator(item: User(name: "Jessica Wood", imageName: "user2")),
MessageCellConfigurator(item: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."),
]
}
Вот и все!
Вы можете легко добавлять новые ячейки без необходимости редактировать код вашего ViewController.
Давайте добавим WarningCell в наше табличное представление.
1. Соответствует протоколу ConfigurableCell.
2. Добавьте TableCellConfigurator для этой ячейки в классе ViewModel.
class WarningCell: UITableViewCell, ConfigurableCell {
@IBOutlet weak var messageLabel: UILabel!
func configure(data message: String) {
messageLabel.text = message
}
}
//cell configurator for WarningCell
TableCellConfigurator<WarningCell, String>(item: "This is a serious warning!")
Для получения дополнительной информации перейдите по этой ссылке