25

How do you get a signal from programmatically made changes to UITextField text property? By using rx.text only reports a signal when the user input the text by keyboard. If you set textField.text programmatically, the signal doesn't fire.

This is how I'm using rx.text

(self.phoneNumberTextField.rx.text).orEmpty.subscribe(onNext: { [weak self] (phone) in
         // do something
    }).addDisposableTo(disposeBag)
    self.phoneNumberTextField.text = "this is for test"

Thank you!

Ethan Cheung
  • 261
  • 1
  • 3
  • 6

4 Answers4

41

I had the same issues, apparently sweeper's answer did not work for me. So here is what I did When I set the text for textfield manually, I call sendActions method on the text field

textField.text = "Programmatically set text." textField.sendActions(for: .valueChanged)

On digging a little bit more, I realized that the rx.text depends on UIControlEvents and these are not triggered when you explicitly set the text.

Hope this helps

AjinkyaSharma
  • 1,870
  • 1
  • 16
  • 26
22

You can add controlEvents to asObservable:

    textField.rx.controlEvent([.editingChanged])
        .asObservable().subscribe({ [unowned self] _ in
            print("My text : \(self.textField.text ?? "")")
        }).disposed(by: bag)
Ramesh R C
  • 644
  • 7
  • 17
  • It works, thank you! but can you explain why need [unowned self] closure? – Pengguna Oct 12 '20 at 07:50
  • 1
    Great! [unowned self] is used for getting a strong reference. So you can use "self. textField" or any strong reference. Here is some good read https://stackoverflow.com/questions/24320347/shall-we-always-use-unowned-self-inside-closure-in-swift – Ramesh R C Oct 13 '20 at 23:58
  • @RameshRC Actually that's not true. [unowned self] is a weak reference, just as [weak self]. The difference is that "unowned" is implicitly unwrapped, so you don't need to use annoying "self?" every time. But if self appears to be nil, you will get a crash. If you want to get a strong reference, you don't need to do anything explicitly - you get a strong reference by default (or you can write unnecessary: [self] _ in) – Roman Nov 18 '21 at 01:57
7

When you wish to observe a property of key-value observing compatible object, just call observe!

Here is an example

textfield.rx.observe(String.self, "text").subscribe(onNext: { s in
    print(s ?? "nil")
}).disposed(by: disposeBag)

This will detect changes to text that are made by both the user and your code.

You can use this technique to not just observe text, but also any other property that has a key path!

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • 4
    This does not work out for me...I only get an empty string event at first and then nothing – andrei Jul 05 '18 at 19:29
  • Although the comment from @andrei is valid, this snippet does work when the `textfield.text` is change programmatically, which was the original question. – erickva Jul 08 '20 at 08:55
-1

If u are setting textfield.text programmatically then you can perform any actions over there. You don't need the subscription block.

As textfield is in inactive state your textfield.text subscription won't get called, rather u have to observe the textfield text.

Use bindings for text changes will solve your problem.

let textChange = Variable(true)
_ = textChange.asObservable().bindTo(textfield.rx.text)
Arnav
  • 668
  • 6
  • 14