基于 UITextField 中的值禁用按钮只能工作一次(RxSwift)

Disabling a button based on value in a UITextField only works once (RxSwift)

我正在尝试掌握 RxCocoa 并且遇到了一个与我尝试实现的某些动态 UI 行为相关的异常错误。

我有一个 UITextField 用于用户输入。将输入添加到 Realm 数据库的按钮绑定到 RxSwift 操作。这绝对没问题。

最初,我禁用了按钮,直到 UITextField 中出现长度至少为 1 个字符的文本 - 此代码工作正常。当我添加对 Action 的 executionObservables 参数的订阅时,我的代码中出现了错误,该参数应在按下按钮后清除 UITextField。

预期行为:

实际行为:

添加 debug() 表明绑定到禁用按钮的 UITextField 已处理,但我无法弄清楚为什么 UIViewController 及其关联视图模型应该仍在范围内。谁能指出我正确的方向?

代码片段:

func bindViewModel() {
    // populate table
    viewModel.output.sectionedObservations
        .drive(tableView.rx.items(dataSource: dataSource))
        .disposed(by: disposeBag)

    // only allow enable button when there is text in the textfield
    observationTextField.rx.text
        .debug()
        .map { [=10=]!.count > 0 }
        .bind(to: addObservationButton.rx.isEnabled)
        .disposed(by: disposeBag)

// clear textfield once Action triggered by button press has completed
viewModel.addObservation.executionObservables
    .subscribe({ [unowned self] _ in
        self.observationTextField.rx.text.onNext("")
})
.disposed(by: disposeBag)

// add Observation to Realm using Action provided by the view model
addObservationButton.rx.tap
    .withLatestFrom(observationTextField.rx.text.orEmpty)
    .take(1)
    .bind(to: viewModel.addObservation.inputs)
    .disposed(by: disposeBag)
}

我认为对 ControlProperty trait 的行为方式存在一些误解。让我们来看看具体的行为是Programmatic value changes won't be reported

订阅后的这个 Observable observationTextField.rx.text 将不会为两者发出事件:

self.observationTextField.rx.text.onNext("")

self.observationTextField.text = ""

我对您的代码有 2 个建议:

1) 手动完成作业:

viewModel.addObservation.executionObservables
    .subscribe({ [unowned self] _ in
        self.observationTextField = ""
        self.addObservationButton.isEnabled = false
})
.disposed(by: disposeBag)

2) 再添加一个 Observable 和订阅:

//a
    viewModel.addObservation.executionObservables
      .map { _ in return "" }
      .bind(to: observationTextField.rx.text)
      .disposed(by: disposeBag)

    viewModel.addObservation.executionObservables
      .map { _ in return false }
      .bind(to: addObservationButton.rx.isEnabled)
      .disposed(by: disposeBag)
//b
    let executionObservables = viewModel.addObservation
      .executionObservables
      .share()

    executionObservables
      .map { _ in return "" }
      .bind(to: observationTextField.rx.text)
      .disposed(by: disposeBag)

    executionObservables
      .map { _ in return false }
      .bind(to: addObservationButton.rx.isEnabled)
      .disposed(by: disposeBag)

不确定 Action 是如何实现的,为了防止工作完成两次,您可能必须共享资源。