Зарегистрируйте и удалите UITableViewCell определенного типа - PullRequest
1 голос
/ 03 мая 2019

UITableView был создан, когда objc уже был «старым» и swift никогда не упоминался.В objc не было никакой необходимости, если вы удалили ячейку из очереди для ее сотворения, вы просто присвоили ее, и все прошло правильно, если у вас была правильная ячейка.другое яблоко) платформа (-ы).

Теперь я снова и снова пишу много шаблонов (определите идентификатор, приведите ячейку, используйте принудительное развертывание фатальной ошибки, ..).

Поэтому я подумал, есть ли идеи, которые могли бы сделать это проще и понятнее в коде.

Ответы [ 2 ]

1 голос
/ 03 мая 2019

@ Сарен, ваше решение работало нормально для одного UITableViewCell, но я сделал несколько улучшений, которые поддерживают несколько UITableViewCell регистраций.

UITableView + extension.swift

public protocol ClassNameProtocol {
    static var className: String { get }
    var className: String { get }
}

public extension ClassNameProtocol {
    public static var className: String {
        return String(describing: self)
    }

    public var className: String {
        return type(of: self).className
    }
}

extension NSObject: ClassNameProtocol {}


public extension UITableView {
    public func register<T: UITableViewCell>(cellType: T.Type) {
        let className = cellType.className
        let nib = UINib(nibName: className, bundle: nil)
        register(nib, forCellReuseIdentifier: className)
    }

    public func register<T: UITableViewCell>(cellTypes: [T.Type]) {
        cellTypes.forEach { register(cellType: $0) }
    }

    public func dequeueReusableCell<T: UITableViewCell>(with type: T.Type, for indexPath: IndexPath) -> T {
        return self.dequeueReusableCell(withIdentifier: type.className, for: indexPath) as! T
    }

    public func registerHeaderFooter<T: UITableViewHeaderFooterView>(HeaderFooterType: T.Type) {
        let className = HeaderFooterType.className
        let nib = UINib(nibName: className, bundle: nil)
        register(nib, forHeaderFooterViewReuseIdentifier: className)
    }

    public func registerHeaderFooter<T: UITableViewHeaderFooterView>(HeaderFooterTypes: [T.Type]) {
        HeaderFooterTypes.forEach { registerHeaderFooter(HeaderFooterType: $0) }
    }
}

Используйте как

fileprivate let arrCells = [ContactTableViewCell.self,ContactDetailsCell.self]
self.register(cellTypes: arrCells)

Примечание: пожалуйста, убедитесь, что ваше имя класса и повторно используемый идентификатор UITableviewCell должны быть одинаковыми.

0 голосов
/ 03 мая 2019

Простой способ решить эту проблему - написать небольшое расширение.

Это решение приведет к ошибке 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
}

И все.Надеюсь, вам понравится идея.Любые другие (лучше или хуже ?) идеи приветствуются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...