RxSwift RxDataSources двухстороннее связывание

У меня есть некоторый код, основанный на примерах RxDataSources: https://github.com/RxSwiftCommunity/RxDataSources/blob/master/Example/Example3_TableViewEditing.swift

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

func setupMethodDataSources() {

    let sections: [ComposeMethodSection] = [ComposeMethodSection(header: "", methodSteps: [])]

    let initialState = MethodSectionedTableViewState(sections: sections)
    let addInitialPlaceholderItems = Observable.of((), (), ())
    let addCommand = Observable.of(addMethodButton.rx.tap.asObservable(), addInitialPlaceholderItems)
        .merge()
        .map(MethodTableViewEditingCommand.addPlaceholderItem)

    let deleteCommand = methodTable.rx.itemDeleted.asObservable()
        .map(MethodTableViewEditingCommand.deleteItem)

    let movedCommand = methodTable.rx.itemMoved
        .map(MethodTableViewEditingCommand.moveItem)

    Observable.of(addCommand, deleteCommand, movedCommand)
        .merge()
        .scan(initialState) { (state: MethodSectionedTableViewState, command: MethodTableViewEditingCommand) -> MethodSectionedTableViewState in
            return state.execute(command: command)
        }
        .startWith(initialState)
        .map {
            $0.sections
        }
        .share(replay: 1)
        .bind(to: methodTable.rx.items(dataSource: methodStepsDataSource))
        .disposed(by: disposeBag)
}

Источник данных methodStepsDataSource устанавливается из следующего статического метода:

static func methodStepsTableDataSource() -> RxTableViewSectionedAnimatedDataSource<ComposeMethodSection> {
    return RxTableViewSectionedAnimatedDataSource(
        configureCell: { dataSource, tableView, indexPath, element in

            guard let cell = tableView.dequeueReusableCell(withIdentifier: ComposeMethodStepCell.reuseIdentifier,
                                                           for: indexPath) as? ComposeMethodStepCell else {
                debugPrint("Failed to create 'ComposeMethodStepCell' cell!?")
                return UITableViewCell()
            }

            cell.methodStepTextView.rx.text = element.description
            return cell
        },
        canEditRowAtIndexPath: { _, _ in
            return true
        },
        canMoveRowAtIndexPath: { _, _ in
            return true
        }
    )
}

Ячейки таблицы довольно просты, они просто содержат одно текстовое представление, каждое из которых доступно для редактирования. Под таблицей у меня есть кнопка сохранения, которая при нажатии должна объединять последние из нескольких текстовых полей в любом месте экрана вместе с последним вводом текста из каждой ячейки таблицы. Чтобы сделать это, из контроллера представления я фиксирую событие нажатия кнопки внутри наблюдаемой и передаю его модели представления во время установки привязок. Код для этого выглядит следующим образом:

viewModel.setupBinds(title: titleTextView.rx.text.asObservable(),
                         summary: summaryTextView.rx.text.asObservable(),
                         description: descriptionTextField.rx.text.asObservable(),
                         /*tableSteps: ???*/
                         save: saveButton.rx.tap.asObservable())

В моделях представления 'setupBinds' я создаю одну наблюдаемую из всех входных наблюдаемых, слитых вместе, вот так (пока игнорируем 'tableSteps'):

let userInputs = Observable.combineLatest(title,
                                           summary,
                                           description,
                                           /*tableSteps*/) { (title, summary, description/*, tableSteps*/) -> DataInputs in
        return DataInputs(title: title, summary: summary, description: description/*, tableSteps: tableSteps*/)
    }

Наконец, я наблюдаю за наблюдаемым нажатием кнопки и комбинирую последние из моих userInputs наблюдаемый как это:

composeSaveAction = save
        .withLatestFrom(userInputs)
        .map { [weak self] userInputs in

        // perform save logic
    }
    composeSaveAction.subscribe().disposed(by: disposeBag)

Все это прекрасно работает до того момента, когда я редактирую один из текстовых представлений таблицы. Первая проблема заключается в том, что изменение ввода текста не распространяется обратно на источник данных. Поэтому я исправил это, изменив строку:

cell.methodStepTextView.rx.text = element.descriptionв 'methodStepsTableDataSource', чтобы:cell.methodStepTextView.rx.textInput <-> element.description (описание теперь Variable<String>

Теперь каждый раз, после внесения изменений в таблицу и нажатия кнопки сохранения, при проверке моих источников данных я мог видеть, что это изменение возвращается из текстового поля. Последняя оставшаяся проблема, однако, заключается в том, как фиксировать изменения источника данных. Всякий раз, когда я редактирую ячейку таблицы, мои 'user Inputs' должны перестраивать новый объект 'DataInputs' (как это происходит при редактировании других входных данных). Тем не менее, я не могу придумать способ наблюдать источники данных за изменениями или событиями таблицы, которые сработают, когда редактирование текстового представления завершится. В идеале это, например, еще один наблюдаемый "tableSteps" (который закомментирован), но точно ли это будет наблюдаться?

Итак, чтобы подвести итог, у меня есть коллекция элементов пользовательского ввода на экране, а затем табличное представление, которое управляется источником rxdatasource. Любые изменения элементов на экране фиксируются, и когда я нажимаю кнопку "Сохранить", я объединяю последние из всех этих элементов и выполняю некоторую логику постоянства. Тем не менее, я не могу придумать, как правильно фиксировать изменения в ячейках таблицы (предпочтительно, в виде массива текстовых строк ввода), несмотря на то, что дошло до того, чтобы вернуть их обратно в мой источник данных.

Извиняюсь за супер длинный пост! Совпадает ли то, что я пытаюсь достичь, с чем-то, что кто-то еще сделал, или у вас есть какие-либо предложения? Спасибо!

0 ответов

Другие вопросы по тегам