Простой способ решить эту проблему - написать небольшое расширение.
Это решение приведет к ошибке fatalError, если будет снята ячейка, которая не была зарегистрирована.Это уже стандартное поведение для iOS, если мы вызываем dequeueReusableCell(withIdentifier:for:)
, если мы не зарегистрировали ячейку.
Чтобы разрешить эту работу, нам нужен способ создания уникального идентификатора для любого типа ячейки, которую мы зарегистрируеми исключить использование дженериков.Если вы хотите иметь возможность снять одну и ту же ячейку в очередь для разных идентификаторов, вам придется вернуться к системе по умолчанию (в этом никогда не было необходимости).
Итак, давайте создадим класс с именем UITableView+Tools.swift
(или как вы хотите его назвать).
extension UITableView {
private func reuseIndentifier<T>(for type: T.Type) -> String {
return String(describing: type)
}
public func register<T: UITableViewCell>(cell: T.Type) {
register(T.self, forCellReuseIdentifier: reuseIndentifier(for: cell))
}
public func register<T: UITableViewHeaderFooterView>(headerFooterView: T.Type) {
register(T.self, forHeaderFooterViewReuseIdentifier: reuseIndentifier(for: headerFooterView))
}
public func dequeueReusableCell<T: UITableViewCell>(for type: T.Type, for indexPath: IndexPath) -> T {
guard let cell = dequeueReusableCell(withIdentifier: reuseIndentifier(for: type), for: indexPath) as? T else {
fatalError("Failed to dequeue cell.")
}
return cell
}
public func dequeueReusableHeaderFooterView<T: UITableViewHeaderFooterView>(for type: T.Type) -> T {
guard let view = dequeueReusableHeaderFooterView(withIdentifier: reuseIndentifier(for: type)) as? T else {
fatalError("Failed to dequeue footer view.")
}
return view
}
}
Так что теперь все, что нам нужно сделать в нашем классе (т.е., посмотреть контроллер), это зарегистрировать ячейку (идентификатор не нужен) и удалить ее из очереди (без идентификатора).без кастинга, принудительного или ручного развертывания с защитой)
func viewDidLoad {
...
tableView.register(MyCustomCell.self)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = dequeueReusableCell(forType: MyCustomCell.self, for: indexPath)
cell.viewModel = cellModel(for: indexPath)
return cell
}
И все.Надеюсь, вам понравится идея.Любые другие (лучше или хуже ?) идеи приветствуются.