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

基于UITextField中的值禁用按钮只工作一次(RxSwift),swift,rx-swift,rx-cocoa,Swift,Rx Swift,Rx Cocoa,我正在努力掌握RxCocoa,遇到了一个与我试图实现的一些动态UI行为相关的异常bug 我有一个UITextField,用于用户输入。将输入添加到领域数据库的按钮绑定到RxSwift操作。这绝对行得通 最初,我禁用了该按钮,直到UITextField中出现至少1个字符的文本为止-该按钮的代码工作正常。我的代码中的错误是在我向操作的executionObservables参数添加订阅时出现的,该参数应在按下按钮后清除UITextField 预期行为: 无文本(初始状态)>按钮已禁用 文本输入>按

我正在努力掌握
RxCocoa
,遇到了一个与我试图实现的一些动态UI行为相关的异常bug

我有一个
UITextField
,用于用户输入。将输入添加到领域数据库的按钮绑定到
RxSwift
操作。这绝对行得通

最初,我禁用了该按钮,直到
UITextField
中出现至少1个字符的文本为止-该按钮的代码工作正常。我的代码中的错误是在我向操作的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)
}

我认为对
ControlProperty
trait的行为有一点误解。让我们来看看具体的行为,即

订阅后,此Observable
observationTextField.rx.text
不会为以下两种情况发出事件:

self.observationTextField.rx.text.onNext(“”)

self.observationTextField.text=”“

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

1) 手动执行此工作:

viewModel.addObservation.executionObservables
.subscribe({[unowned self]\uuin
self.observationTextField=“”
self.addObservationButton.isEnabled=false
})
.处置(由:处置人)
2) 再添加一个可观察和订阅:

/a
viewModel.addObservation.executionObservables
.map{作为返回“”}
.bind(到:observationTextField.rx.text)
.处置(由:处置人)
viewModel.addObservation.executionObservables
.map{返回false}
.bind(到:addObservationButton.rx.isEnabled)
.处置(由:处置人)
//b
让executionObservables=viewModel.addObservations
.可观察到的处决
.share()
可观察的处决
.map{作为返回“”}
.bind(到:observationTextField.rx.text)
.处置(由:处置人)
可观察的处决
.map{返回false}
.bind(到:addObservationButton.rx.isEnabled)
.处置(由:处置人)

不确定如何执行
操作
,为了防止工作重复两次,您可能必须共享资源。

除了您的问题之外,这个
$0!。计数>0
是等待发生的崩溃。替换为安全操作,如<代码>($0?.count±0)>0我知道,但感谢您的突出显示。这是一个快速、实验性的代码,显然需要重构来处理可怕的可选代码!如果我理解正确,您最终需要viewModel告诉
observationTextField
它的值应该是什么。我养成了为viewModel的每个输出创建
驱动程序的习惯,然后将其绑定到文本字段。使用它来替换您的
viewModel.addObservation.executionobservates
我确实需要通过编程修改UITextField的内容,但只是删除它,这样我就不会认为我需要来自视图模型的直接输入。使用executionObservables可以确保正确执行操作,并且由于修改的目的是将.text属性设置为“”,因此我认为一种简单的方法最好是感谢steer Sergey。这就是诀窍,现在我明白我做错了什么(希望再次犯这个错误!)快速思考:在这个上下文中,is.don't preferred.subscribe(onNext:),因为我们正在执行UI副作用,而不是更改流中的元素?用户界面的手动更新比其他版本更紧凑(即使有额外的一行),而且同样具有表现力。我现在有了预期的行为。再次感谢我,我对这两个都很满意:
swift viewModel.addObservation.executionobservates.do(onNext:{in self.observationTextField=”“self.addObservationButton.isEnabled=false})。subscribe().disposed(by:disposeBag)
swift viewModel.addObservation.executionObservables.subscribe({[unowned self]\uIn self.observationTextField=”“self.addObservationButton.isEnabled=false})。disposed(by:disposeBag)
我个人更喜欢subscribe闭包中的代码。