1

我将 MVVM 模式与RxSwiftRxCocoaRxDataSources 一起使用

在此处输入图像描述

我已经通过使用成功填充了存在的UITableView数组,但它是一种方式绑定。PaletteViewModelListViewModelRxDataSource

我想实现我在图片中显示的内容,即我想将UITextFieldfrom绑定UITableViewCellObservable数组中某个索引处存在的ListViewModel

我想2 way binding处理. UITextField_ 如果用户更改 textField 中的文本,它应该更改特定索引处存在的 answer 属性中的值,反之亦然。answerPaletteViewModel

MVVM pattern我怎样才能使用ReactiveX框架来实现这样复杂的事情?

如果UITableViewCellat someIndexPath由于不可见而从内存中删除,并且 observable 的值发生更改,会导致崩溃,因为UITextFieldatIndexPath将返回 nil?

4

1 回答 1

3

AUITextField输入元素。您不需要对它进行双向绑定,因为您不应该动态更改它。你应该做的最多就是初始化它,你不需要为此绑定。

你没有提到这个输入的最终输出是什么,所以答案可能与下面的不同。此特定解决方案假定您需要将所有答案作为一个组推送到服务器或数据库。也许当一个按钮被点击时。

下面有很多代码,但它按原样编译(使用正确的导入)。您可以订阅以ListViewModel.answers查看收集在一起的所有答案。

class ViewController: UIViewController {

    @IBOutlet weak var myTableView: UITableView!
    let bag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        let answersSubject = PublishSubject<(PaletteID, String)>()
        let viewModel = ListViewModel(answersIn: answersSubject.asObservable())

        viewModel.paletteViewModels
            .bind(to: myTableView.rx.items(cellIdentifier: "Cell", cellType: MyCell.self)) { index, element, cell in
                cell.answerTextField.text = element.initialAnswer
                cell.answerTextField.rx.text.orEmpty
                    .map { (element.id, $0) }
                    .bind(to: answersSubject)
                    .disposed(by: cell.bag)
            }
            .disposed(by: bag)
    }
}

class MyCell: UITableViewCell {
    @IBOutlet weak var answerTextField: UITextField!
    let bag = DisposeBag()
}

struct ListViewModel {
    let paletteViewModels: Observable<[PaletteViewModel]>
    let answers: Observable<[PaletteID: String]>

    init(answersIn: Observable<(PaletteID, String)>) {
        paletteViewModels = Observable.just([])
        answers = answersIn
            .scan(into: [PaletteID: String]()) { current, new in
                current[new.0] = new.1
            }
    }
}

struct PaletteViewModel {
    let id: PaletteID
    let initialAnswer: String
}

struct PaletteID: RawRepresentable, Hashable {
    let rawValue: String
}
于 2019-02-10T02:39:50.010 回答