Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public protocol CellRepresentable {
- static var reuseIdentifier: String { get }
- }
- public extension CellRepresentable {
- static var reuseIdentifier: String {
- return String(describing: Self.self)
- }
- }
- public typealias ViewModelConfigurable = Configurable & AnyConfigurable
- public protocol Configurable {
- associatedtype ViewModel
- func configure(with model: ViewModel)
- }
- public protocol AnyConfigurable {
- func configure(with model: Any)
- }
- public extension AnyConfigurable where Self: Configurable {
- func configure(with model: Any) {
- guard let viewModel = model as? ViewModel else { return }
- configure(with: viewModel)
- }
- }
- // Создает дата сурс, способный извлекать события из ячеек таблицы (damn good, right?)
- /// Для этого возвращает промежуточное замыкание в котором имеем объект содержащий эмиттер (иными словами - rx-subject)
- /// Содержащий интересующие нас события из ячеек
- /// В этом замыкании необходимо обработать эмиттер как правило построить биндинг
- /// S - тип возвращаемого ивента
- func eventEmittableDataSource<T: SectionModelType, S>()
- -> (_ emittersHandler: @escaping (S) -> Void)
- -> RxTableViewSectionedReloadDataSource<T> {
- return { emittersHandler in
- let dataSource = RxTableViewSectionedReloadDataSource<T>(configureCell: { dataSource, tableView, indexPath, model -> UITableViewCell in
- guard let model = model as? CellRepresentable else { return UITableViewCell() }
- let cell = tableView.dequeueReusableCell(withIdentifier: type(of: model).reuseIdentifier, for: indexPath)
- if let configurableCell = cell as? AnyConfigurable {
- configurableCell.configure(with: model)
- }
- if let emitterCell = cell as? AnyEventsCollector {
- let events = EventsCollectableViewModel<S>(viewModel: emitterCell).collectEvents()
- emittersHandler(events)
- }
- return cell
- })
- return dataSource
- }
- }
- public func defaultDataSource<T: SectionModelType>() -> RxTableViewSectionedReloadDataSource<T> {
- let dataSource = RxTableViewSectionedReloadDataSource<T>(configureCell: { dataSource, tableView, indexPath, model -> UITableViewCell in
- guard let model = model as? CellRepresentable else { return UITableViewCell() }
- let cell = tableView.dequeueReusableCell(withIdentifier: type(of: model).reuseIdentifier, for: indexPath)
- if let configurableCell = cell as? AnyConfigurable {
- configurableCell.configure(with: model)
- }
- return cell
- })
- return dataSource
- }
- /// Это реализовываем во всем что может создавать события (etc. - ячейка)
- public typealias EventsEmitter = AnyEventsCollector & EventsCollector
- /// Внутренняя реализация
- /// Структура для избежания каста в дата сурсах
- /// или на любой принимающей стороне
- /// Необходимо быть осторожным с типами, если ивент не совпадет - крашится
- /// Тип ивента должен совпадать с тем что возвращает эмиттер
- struct EventsCollectableViewModel<E>: EventsCollector {
- private let viewModel: AnyEventsCollector
- init(viewModel: AnyEventsCollector) {
- self.viewModel = viewModel
- }
- func collectEvents() -> E {
- guard let event = collectEvents() as? Event else {
- fatalError("Event not casted")
- }
- return event
- }
- }
- /// Протокол для обхода ограничения на генерик параметры
- /// для передачи эмиттера в функции использовать его
- /// После чего обернуть в структуру выше и уже у нее дергать ивенты
- /// Или же использовать каст из Any но это менее красиво
- public protocol AnyEventsCollector {
- func collectEvents() -> Any
- }
- public extension AnyEventsCollector where Self: EventsCollector {
- func collectEvents() -> Any {
- return collectEvents() as Event
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement