RxSwift RxDataSources双向绑定

时间:2018-01-30 21:00:35

标签: swift uitableview rx-swift 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'中我正在从所有输入的observable中创建一个observable,就像这样合并在一起(暂时忽略'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>

现在每次进行表格编辑和点击保存后,我都可以看到我的数据源检查到这个更改是从文本字段反馈的。然而,我遇到的最后一个问题是如何捕获数据源更改。每当我编辑一个表格单元格时,我的“userInputs”需要重建一个新的“DataInputs”对象(就像编辑其他输入时一样)。但是,我无法想到一种方法来观察更改的数据源或在编辑文本视图时将触发的表事件。理想情况下,这将是另一个可观察的'tableSteps'(已被注释掉),但究竟会观察到吗?

因此,总结一下,我在屏幕上有一组用户输入元素,后跟一个由rxdatasource驱动的表视图。捕获对屏幕上元素的任何编辑,当我点击“保存”按钮时,我将组合所有这些元素中的最新元素并执行一些持久性逻辑。然而,我无法想出一种简洁的方法来捕获我的表格单元格编辑(最好是一组文本输入字符串),尽管已经到了将数据反馈到我的数据源中。

为超长的帖子道歉!我在这里想要实现的是否与其他人做过的事情一致,或者你有什么建议吗?谢谢!

0 个答案:

没有答案