Swift (RxSwift): использование шаблонов для связывания классов ViewItem и Cell - PullRequest
0 голосов
/ 27 ноября 2018

Я выполняю рефакторинг реализации UITableView в RxSwift .У меня есть разные элементы просмотра, и я хочу переключить их, чтобы я мог соответствующим образом настроить свой источник данных.Мне нужно знать, какой класс ячеек принадлежит какому элементу представления.

Для этого я написал метод, который берет элемент, который реализует мой ViewItemProtocol и возвращает AnyClass?.

func getAssociatedtCellType<T>(for item: T) -> AnyClass? where T: ViewItemProtocol {
    switch item  {
    case is TextFieldViewItem: return TextFieldCell.self
    case is FaqDetailViewItem: return FaqCell.self
    case is HeaderViewItem: return HeaderCell.self
    case is SubmitButtonViewItem: return SubmitButtonCell.self
    case is BankDetailViewItem: return BankDetailCell.self
    case is EmailViewItem: return EmailCell.self
    default: return nil
    }
}

Метод функции настроил мою ячейку:

private func configCell<T>(for item: T, with identifier: String, at indexPath: IndexPath) -> UITableViewCell where T: ViewItemProtocol {
    guard let cellType = getAssociatedtCellType(for: item.self) else { return UITableViewCell() }
    guard let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath) as? cellType else { fatalError() }
    cell.configureBindings(itemSource: item)
    return cell
}

Проблема возникает с cellType:

Использование необъявленного типа 'cellType'

Цель состоит в том, чтобы реорганизовать этот метод:

private func dataSource() -> RxTableViewSectionedReloadDataSource<SectionedViewItem> {

    let dataSource = RxTableViewSectionedReloadDataSource<SectionedViewItem>(configureCell: { [unowned self] _, tableView, indexPath, item in

        switch item {
        case let item as TextFieldViewItem:
            guard let cell = tableView.dequeueReusableCell(withIdentifier: TextFieldCell.Key, for: indexPath) as? TextFieldCell else { fatalError() }
            cell.configureBindings(itemSource: item)
            cell.changeButton.isHidden = item.editable
            cell.changeButton.addTarget(self, action: #selector(self.showFieldNotEditableAlert), for: .touchUpInside)
            cell.textField.addTarget(self, action: #selector(self.textFieldDidChange), for: .editingChanged)
            return cell

        case let item as FaqDetailViewItem:
            guard let cell = tableView.dequeueReusableCell(withIdentifier: FaqDetailCell.Key, for: indexPath) as? FaqDetailCell else { fatalError() }
            cell.configureBindings(itemSource: item)
            return cell

        case let item as PasswordTextFieldViewItem:
            guard let cell = tableView.dequeueReusableCell(withIdentifier: PasswordTextFieldCell.Key, for: indexPath) as? PasswordTextFieldCell else { fatalError() }
            cell.configureBindings(itemSource: item)
            return cell

        case let item as HeaderViewItem:
            guard let cell = tableView.dequeueReusableCell(withIdentifier: HeaderCell.Key, for: indexPath) as? HeaderCell else { fatalError() }
            cell.configureBindings(itemSource: item)
            return cell

// ... My other cell types... :-(

    })

    dataSource.titleForHeaderInSection = { dataSource, index in
        let section = dataSource[index]
        return section.header
    }

    return dataSource
}

... в нечто вроде этого:

private func dataSource() -> RxTableViewSectionedReloadDataSource<SectionedViewItem> {

    let dataSource = RxTableViewSectionedReloadDataSource<SectionedViewItem>(configureCell: { [unowned self] _, tableView, indexPath, item in

        switch item {
        case let item as TextFieldViewItem:
            guard let cell = tableView.dequeueReusableCell(withIdentifier: TextFieldCell.Key, for: indexPath) as? TextFieldCell else { fatalError() }
            cell.configureBindings(itemSource: item)
            cell.changeButton.isHidden = item.editable
            cell.changeButton.addTarget(self, action: #selector(self.showFieldNotEditableAlert), for: .touchUpInside)
            cell.textField.addTarget(self, action: #selector(self.textFieldDidChange), for: .editingChanged)
            return cell

        case let item as FaqDetailViewItem, let item as PasswordTextFieldViewItem, let item as HeaderViewItem:
            return configCell(for: item, with: "Cell.Key... still to implement)", at: indexPath)


        default:
            return UITableViewCell()
        }

    })

    dataSource.titleForHeaderInSection = { dataSource, index in
        let section = dataSource[index]
        return section.header
    }

    return dataSource
}

1 Ответ

0 голосов
/ 28 ноября 2018

К сожалению, это не может быть сделано в Swift.В быстром, компилятор должен знать типы переменных во время компиляции, но в вашем случае вы пытаетесь уменьшить во время выполнения.Так что нет, вы не сможете этого сделать.

Вы, вероятно, сможете выполнить это с помощью какого-то преобразования с использованием обобщений во время выполнения, но приведение не позволит вам получить доступ к свойствам этого класса, что, вероятно, является тем, что вам нужно для выполнения всех привязок.,Я думаю, что вам будет лучше переместить код, который вы используете в своем выражении switch, в установку tableViewCell.

...