1

I want to use RxSwift to get the text from a UITextField after the UIControlEvent Editing Changed is triggered.

In Order to do that:

I connected the textfield outlet from storyboard to my view controller like that.

@IBOutlet weak var currentPasswordTextField: UITextField!

and then on the didSet property of this textfield I tried this:

@IBOutlet weak var currentPasswordTextField: UITextField!{
    didSet{
        currentPasswordTextField
            .rx
            .controlEvent(.editingChanged)
            .asObservable()
            .subscribe(onNext: { (text) in
            //I want here to print the text after the editing changed. 
               print(text)
            })
            .disposed(by: disposeBag)
    }
}

but the text is Void not a string..

if anyone can help Id be grateful. thanks in advance.

P.S. I don't want to use IBActions.

MhmdRizk
  • 1,591
  • 2
  • 18
  • 34

3 Answers3

14

Some points:

  • asObservable() is unnecessary.
  • you could subscribe to .rx.text.orEmpty directly, but then you will get events when the text field begins and ends editing.

Here you go:

@IBOutlet weak var currentPasswordTextField: UITextField!{
    didSet{
        currentPasswordTextField
            .rx
            .controlEvent(.editingChanged)
            .withLatestFrom(currentPasswordTextField.rx.text.orEmpty)
            .subscribe(onNext: { (text) in
                //I want here to print the text after the editing changed.
                print(text)
            })
            .disposed(by: disposeBag)
    }
}

Something else I thought of last night...

Putting this code in the didSet is going to be a problem. Rx code tends to be output centric, not input centric. Because of this, whatever goes in the subscribe will likely reference some other object that also has to exist and you are likely going to want to be able to reference other observables too.

What do I mean by input vs output centric?

Imperative code tends to be input centric, when you want to know what's going to happen when a button is tapped, you usually have one place to look, the button's action. However, if you want to understand everything that affects a particular label, activity indicator or any other output, you have to look all over the code. Every function in the view controller could be pushing information to the output and several of them likely are.

Declarative code tends to be output centric, when you want to know everything that affects a label's output, or what causes the activity indicator to show/hide, there is generally one place to look. However, if you want to understand everything that tapping a button does, you will have to look all over the code to figure it out. (A perfect example of this is a spreadsheet, if you want to know how the output for a particular cell is defined, you only need to look at the formula in that cell, but if you want to know all the cells that are affected by a particular cell, that's a pain.)

In my experience, the above is the hardest thing for programmers to wrap their heads around when working with Rx.

Community
  • 1
  • 1
Daniel T.
  • 32,821
  • 6
  • 50
  • 72
1

You want to subscribe to currentPasswordTextField.rx. text (or .text.orEmpty if you don't want optional string) instead of the control event itself.

Under the hood, .text (which is an alias of .value) observes control events [.allEditingEvents, .valueChanged] and returns the value.

More details:

Rax
  • 785
  • 4
  • 14
  • The fact that `.rx.text` fires events on `.allEditingEvents` is precisely why he might want to subscribe to the control event itself. :-) But you are right that it is rarely necessary to be that restrictive. – Daniel T. Oct 20 '18 at 12:58
0

didSet on the UITextField will only be trigger if you replace the UITextField itself but not when you set the text on it.

// Does not trigger didSet :
self.currentPasswordTextField.text = "text"
// Does trigger didSet
self.currentPasswordTextField = UITextField()
Sylvain
  • 118
  • 8
  • Hello sylvain as i mentioned in my question, I want to use only RxSwift without using any IBActions. – MhmdRizk Oct 19 '18 at 15:25