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

时间:2019-05-31 13:13:06

标签: swift rx-swift rx-cocoa

我正在尝试RxCocoa,并遇到了一个与我要实现的动态UI行为有关的不寻常的错误。

我有一个UITextField用于用户输入。将输入添加到Realm数据库的按钮绑定到RxSwift Action。绝对可以。

最初,我禁用了按钮,直到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 { $0!.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)
}

1 个答案:

答案 0 :(得分:1)

我认为ControlProperty特质的表现有些误解。让我们看一下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的实现方式,以防止重复执行两次工作,也许您必须共享资源。