8

I am trying to build an Observable which would output a value based on the value of a Variable.

Something like that:

let fullName = Variable<String>("")
let isFullNameOKObs: Observable<Bool>

isFullNameOKObs = fullName
            .asObservable()
            .map { (val) -> Bool in
                // here business code to determine if the fullName is 'OK'
                let ok = val.characters.count >= 3
                return ok
            }

Unfortunately the bloc in the map func is never called!

The reason behind this is that:

  1. The fullName Variable is binded to a UITextField with the bidirectional operator <-> as defined in the RxSwift example.
  2. The isFullNameOKObs Observable will be observed to hide or display the submit button of my ViewController.

Any help would be greatly appreciated.

Thanks

The model

class Model {

    let fullName = Variable<String>("")
    let isFullNameOKObs: Observable<Bool>

    let disposeBag = DisposeBag()

    init(){

        isFullNameOKObs = fullName
            .asObservable()
            .debug("isFullNameOKObs")
            .map { (val) -> Bool in
                let ok = val.characters.count >= 3
                return ok
            }
            .debug("isFullNameOKObs")


        isRegFormOKObs = Observable.combineLatest(
            isFullNameOKObs,
            is...OK,
            ... ) { $0 && $1 && ... }


        isRegFormOKObs
            .debug("isRegFormOKObs")
            .asObservable()
            .subscribe { (event) in
                // update the OK button
            }
            // removing this disposedBy resolved the problem
            //.disposed(by: DisposeBag())

    }
}

The ViewController:

func bindModel() -> Void {

    _ = txFullName.rx.textInput <-> model!.fullName
    ......

}
t4ncr3d3
  • 615
  • 1
  • 8
  • 17
  • Resolved but I don't understand how. I use the same pattern for each TextField of the form: an Observable named isMyTextFieldOK that computes some business rules. A final observable that is a combineLatest of all isMyTextFieldOK observables. I did attach a disposed(by: disposeBag) call on this last observable. Removing it resolved everything. But I don't know why. :-( – t4ncr3d3 Mar 07 '17 at 20:55

1 Answers1

4

Do you need the two-way binding between the UITextField and your Variable?

If not, I would suggest you try to just use bindTo() instead like this: myTextField.rx.text.orEmpty.bindTo(fullName).disposed(by: disposeBag)

BStien
  • 41
  • 3
  • Doesn't change. The Variable is correctly updated by the UITextField. But the value of Observable still doesn't reflect the correct situation. – t4ncr3d3 Mar 07 '17 at 20:46
  • How do you bind `isFullNameOKObs` to your button? Please share the code you're using – BStien Mar 07 '17 at 20:59
  • Still haven't determined how to do it. – t4ncr3d3 Mar 07 '17 at 21:06
  • The correct way, as I've learned it, is this: `isFullNameOKObs.bindTo(myButton.rx.isEnabled).disposed(by: disposeBag)`. Regarding your comment about the removal of `disposed(by: disposeBag)`: this may be because your prematurely disposing your subscriptions, ie. by setting `disposeBag = nil` in your code. – BStien Mar 07 '17 at 21:16